Blazorise DataGrid to Add dropdown list - datagrid

I'm Beginner to Blazorise and I'm usinf Blazorise DataGrid, but I faced some conflict anyone know how to add Operation label click and show Edit,View dropdown list
Thanks
image description here
code here
<Div Class="mt-3">
<DataGrid TItem="Employee"
Data="#employeeList"
#bind-SelectedRow="#selectedEmployee"
PageSize="5"
Responsive="true"
ShowPager="true"
Resizable
Bordered="true"
Striped="true"
Hoverable="true"
>
<DataGridColumns>
<DataGridColumn Field="#nameof(Employee.Id)" Caption="#" Sortable="false" />
<DataGridColumn Field="#nameof(Employee.UserGroupName)" Caption="Group Name" />
<DataGridColumn Field="#nameof(Employee.UserName)" Caption="Last Name" />
<DataGridColumn Field="#nameof(Employee.PermissionType)" Caption="Permission Type" />
<DataGridColumn Field="#nameof(Employee.Operation)" Caption="Operation" >
</DataGridColumn>
</DataGridColumns>
</DataGrid></Div>
#* END TRUSTED USER LIST*#
</CardBody></Card>
</Column>
</Row>
</Div>
#code{
private List<Employee> employeeList;
private Employee selectedEmployee;
protected override async Task OnInitializedAsync()
{
employeeList = new List<Employee>()
{
new Employee{ Id="1",UserGroupName="Tesxt",UserName="test1",PermissionType="test#gmail.com",Operation="Operation"},
new Employee{ Id="2",UserGroupName="Tesxt",UserName="test1",PermissionType="test#gmail.com",Operation="Operation"},
new Employee{ Id="3",UserGroupName="Tesxt",UserName="test1",PermissionType="test#gmail.com",Operation="Operation"},
new Employee{ Id="4",UserGroupName="Tesxt",UserName="test1",PermissionType="test#gmail.com",Operation="Operation"},
new Employee{ Id="5",UserGroupName="Tesxt",UserName="test1",PermissionType="test#gmail.com",Operation="Operation"},
new Employee{ Id="6",UserGroupName="Tesxt",UserName="test1",PermissionType="test#gmail.com",Operation="Operation"},
new Employee{ Id="7",UserGroupName="Tesxt",UserName="test1",PermissionType="test#gmail.com",Operation="Operation"},
new Employee{ Id="8",UserGroupName="Tesxt",UserName="test1",PermissionType="test#gmail.com",Operation="Operation"},
new Employee{ Id="9",UserGroupName="Tesxt",UserName="test1",PermissionType="test#gmail.com",Operation="Operation"},
new Employee{ Id="10",UserGroupName="Tesxt",UserName="test1",PermissionType="test#gmail.com",Operation="Operation"},
};
await base.OnInitializedAsync();
}
public class Employee
{
public string Id { get; set; }
public string UserGroupName { get; set; }
public string UserName { get; set; }
public string PermissionType { get; set; }
public string Operation { get; set; }
}
}

You can use <DisplayTemplate> to customize display cells
<DataGridColumn Field="#nameof(Employee.Operation)" Caption="Operation">
<DisplayTemplate>
<Dropdown>
...
</Dropdown>
</DisplayTemplate>
</DataGridColumn>
Official documentation: https://blazorise.com/docs/extensions/datagrid/templates
Lots of DataGrid examples here

Related

How can I Bind a List of custom class objects to a Gridview's Datasource (getting "A field or property ... not found on the ... data source")?

To avoid querying the Database on the first loading of the page, I want to populate a List of a custom class to the GridView.
I'm trying to do it this way:
protected void Page_Load(object sender, EventArgs e)
{
List<MoviesGridDisplayColumns> listStartupData = new List<MoviesGridDisplayColumns>();
MoviesGridDisplayColumns mgdc;
mgdc = new MoviesGridDisplayColumns();
mgdc.MovieTitle = "War of the Buttons";
mgdc.MPAARating = "PG";
mgdc.IMDBRating = 7.5;
mgdc.Minutes = 94;
mgdc.YearReleased = "1994";
listStartupData.Add(mgdc);
mgdc = new MoviesGridDisplayColumns();
mgdc.MovieTitle = "The Trip to Bountiful";
mgdc.MPAARating = "PG";
mgdc.IMDBRating = 7.5;
mgdc.Minutes = 108;
mgdc.YearReleased = "1985";
listStartupData.Add(mgdc);
. . .
GridView1.DataSource = listStartupData;
GridView1.DataBind();
...but on the penultimate line above I get:
"System.Web.HttpException HResult=0x80004005 Message=A field or
property with the name 'MovieTitle' was not found on the selected data
source."
The selected data source is the List of MoviesGridDisplayColumns objects, which does indeed have a MovieTitle member. So what gives?
The custom class is:
public class MoviesGridDisplayColumns
{
public string MovieTitle = string.Empty;
public double IMDBRating = 0.0;
public string MPAARating = string.Empty;
public string YearReleased = string.Empty;
public int Minutes;
}
...and the GridView appears in the .aspx file thus:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" OnDataBound="GridView1_DataBound" OnPreRender="GridView1_PreRender">
<Columns>
<asp:BoundField DataField="MovieTitle" HeaderText="MovieTitle" SortExpression="MovieTitle" />
<asp:BoundField DataField="IMDBRating" HeaderText="IMDBRating" SortExpression="IMDBRating" />
<asp:BoundField DataField="MPAARating" HeaderText="MPAARating" SortExpression="MPAARating" />
<asp:BoundField DataField="YearReleased" HeaderText="YearReleased" SortExpression="YearReleased" />
<asp:BoundField DataField="Minutes" HeaderText="Minutes" SortExpression="Minutes" />
</Columns>
</asp:GridView>
The fields in your class are missing the getter methods. You can change the MoviesGridDisplayColumns to the following.
public class MoviesGridDisplayColumns
{
public string MovieTitle { get; set; } = string.Empty;
public double IMDBRating { get; set; } = 0.0;
public string MPAARating { get; set; } = string.Empty;
public string YearReleased { get; set; } = string.Empty;
public int Minutes { get; set; }
}

Blazorise Datagrid inline edit for complex object

The Blazorise Datagrid supports inline editing. In my code, the basic editing works fine but when an object is used as a property in my parent object, editing does not work as expected.
Below, the city the value not updated as expected. What is missing to allow for a proper edit?
Code
<DataGrid Data="forecasts" TItem="WeatherForecast" EditMode="Blazorise.DataGrid.DataGridEditMode.Inline">
<DataGridCommandColumn TItem="WeatherForecast" CellsEditableOnEditCommand="true"></DataGridCommandColumn>
<DataGridDateColumn TItem="WeatherForecast" Field="#nameof(WeatherForecast.Date)" Caption="Date" Editable="true"></DataGridDateColumn>
<DataGridDateColumn TItem="WeatherForecast" Field="#nameof(WeatherForecast.Temperature)" Caption="Temperature" Editable="true"></DataGridDateColumn>
<DataGridSelectColumn TItem="WeatherForecast" Field="#nameof(WeatherForecast.City)" Caption="City" Editable="true">
<DisplayTemplate>
#{
var name = (context as WeatherForecast).City?.Name;
#name
}
</DisplayTemplate>
<EditTemplate>
#{
<Select TValue="City"
SelectedValue=
"#((City)(((CellEditContext)context).CellValue))"
SelectedValueChanged=
"#( v => ((CellEditContext)context).CellValue = v)">
#foreach (var item in Cities)
{
<SelectItem TValue="City" Value="#(item)">
#item.Name
</SelectItem>
}
</Select>
}
</EditTemplate>
</DataGridSelectColumn>
</DataGrid>
Code Section
#code {
private List<WeatherForecast> forecasts;
private List<City> Cities;
protected override async Task OnInitializedAsync()
{
forecasts = await ForecastService.GetForecastAsync(DateTime.Now); // get list of forecast
Cities = await ForecastService.GetCityListAsync(); // get list of cities
}}
Model classes
public class WeatherForecast
{
public int Id { get; set; }
public DateTime Date { get; set; }
public int Temperature { get; set; }
public City City { get; set; }
}
public class City
{
public int Id { get; set; }
public string Name { get; set; }
}
Try this workaround since Select component doesn't support complex objects binding:
<EditTemplate>
<Select
TValue="int"
SelectedValue="#((int)((City)(((CellEditContext)context).CellValue)).Id)"
SelectedValueChanged=
"#( v => ((CellEditContext)context).CellValue = Cities.First(x=> x.Id == v))">
#foreach (var item in Cities)
{
<SelectItem TValue="int" Value="#(item.Id)">#item.Name</SelectItem>
}
</Select>
</EditTemplate>

Data not displaying in columns in grid UWP

I have a database linked to my grid. When adding data a new checkbox appears, so it is registering that something has been entered, but, the columns are all blank.
Im pretty sure the issue is that I have the bindings set up for the class Person. Could I either still use this class with some additional code, or, find a way to separate the data from the database into columns?
Relevant Code:
Database Class method:
public static List<string> Grab_Entries()
{
List<string> entries = new List<string>();
using (SqliteConnection db = new SqliteConnection("Filename=sqliteSample.db"))
{
db.Open();
SqliteCommand selectCommand = new SqliteCommand("SELECT * from EmployeeTable", db);
SqliteDataReader query;
try
{
query = selectCommand.ExecuteReader();
}
catch (SqliteException)
{
//Handle error
return entries;
}
while (query.Read())
{
entries.Add(query.GetString(0));
}
db.Close();
}
return entries;
MainPage method:
public void EmployeeGrid_Loaded(object sender, RoutedEventArgs e)
{
EmployeeGrid.ItemsSource = DB.Grab_Entries();
}
Main Page XAML:
<controls:DataGrid x:Name="EmployeeGrid" Margin="170,55,35,35"
ItemsSource="{x:Bind persons}"
CanUserSortColumns="True"
AutoGenerateColumns="False" Background="Black" Loaded="EmployeeGrid_Loaded">
<controls:DataGrid.Columns>
<controls:DataGridTextColumn Header="Employee ID"
Binding="{Binding PersonId}"/>
<controls:DataGridTextColumn Header="First Name"
Binding="{Binding FirstName}"/>
<controls:DataGridTextColumn Header="Last Name"
Binding="{Binding LastName}"/>
<controls:DataGridTextColumn Header="Address"
Binding="{Binding Address}"/>
<controls:DataGridTextColumn Header="Position"
Binding="{Binding Position}"/>
<controls:DataGridTextColumn Header="Pay Rate (ph)"
Binding="{Binding PayratePH}"/>
<controls:DataGridTextColumn Header="Sex"
Binding="{Binding Sex}"/>
<controls:DataGridTextColumn Header="TaxCode"
Binding="{Binding TaxCode}"/>
<controls:DataGridTextColumn Header="Email"
Binding="{Binding Email}"/>
<controls:DataGridTextColumn Header="Emergency Contact"
Binding="{Binding EmergencyDetails}"/>
<controls:DataGridCheckBoxColumn Header="Selected"
/>
</controls:DataGrid.Columns>
</controls:DataGrid>
Ill add my Person class too:
public class Person
{
public int PersonId { get; set; }
public int DepartmentId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Position { get; set; }
public string Address { get; set; }
public double PayratePH { get; set; }
public string Sex { get; set; }
public string TaxCode { get; set; }
public string EmergencyDetails { get; set; }
public string Email { get; set; }
I can spot two things here. First, the main page XAML binds the items source to persons, which gets overwritten with the return value of DB.Grab_Entries() whenever the control loads.
In EmployeeGrid_Loaded(), you should be populating the collection that the ItemsSource is bound to (persons), instead of assigning a new collection.
The loaded event should look something like this:
public void EmployeeGrid_Loaded(object sender, RoutedEventArgs e)
{
this.persons.Clear();
this.persons.AddRange(DB.Grab_Entries());
}
P.S. make sure that the ItemsSource collection is of type ObservableCollection, because otherwise it will not update the binding when the elements change.
Second, the method DB.Grab_Entries() returns a list of strings, but by the looks of it, the data grid and the persons collection is expecting a list of person objects with certain properties.
When you're reading the data from the sqlite query, you're getting a single column of data at a time (query.GetString(0)). You'll need to construct an object with all column values and put the object into a list.
As #Darius S. mentioned, the ItemsSource of DataGrid you bound with is the lists of Person class, however, the DB.Grab_Entries() method returns the lists of string type, so the DataGrid can't display well. In your Grab_Entries method, you could get the value each property and then convert them into the Person class. After that, add the Person class into entries lists.
In addition, it is recommended to use ObservableCollection class, when you insert or remove data from this class, it will automatically update the UI. So it's better to return ObservableCollection type from your Grab_Entries method directly. I take the FirstName property as an example:
public async static Task<ObservableCollection<Person>> Grab_Entries()
{
ObservableCollection<Person> entries = new ObservableCollection<Person>();
string dbpath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "sqliteSample.db");
using (SqliteConnection db = new SqliteConnection($"Filename={dbpath}"))
{
db.Open();
SqliteCommand selectCommand = new SqliteCommand("SELECT * from EmployeeTable", db);
using (var reader = await selectCommand.ExecuteReaderAsync())
{
var nameOrdinal = reader.GetOrdinal("First_Name");
//The same method to get other properties
while (await reader.ReadAsync())
{
entries.Add(new Person() { FirstName = reader.GetString(nameOrdinal) });
}
}
db.Close();
}
return entries;
}
MainPage.cs:
ObservableCollection<Person> persons;
public async void EmployeeGrid_Loaded(object sender, RoutedEventArgs e)
{
persons = await Person.Grab_Entries();
EmployeeGrid.ItemsSource = persons;
}

LINQ to XML & bind to Gridview

I am reading data from XML like this:
(Contacts.xml)
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!--LINQ to XML Contacts XML Example-->
<?MyApp 123-44-4444?>
<contacts>
<contact>
<name>Patrick Hines</name>
<phone type="home">206-555-0144</phone>
<phone type="work">425-555-0145</phone>
<address>
<street1>123 Main St</street1>
<city>Mercer Island</city>
<state>WA</state>
<postal>68042</postal>
</address>
</contact>
<contact>
<name>Gretchen Rivas</name>
<phone type="mobile">206-555-0163</phone>
<address>
<street1>123 Main St</street1>
<city>Mercer Island</city>
<state>WA</state>
<postal>68042</postal>
</address>
</contact>
</contacts>
My code for getting data from XML file:
(contacts.cs)
public class Contact
{
//static members
public static string fLocation;
//private members
private string name;
private List<PhoneNumber> pNumber;
private Adress cAdress;
//public members
public Adress CAdress
{
get { return cAdress; }
}
public List<PhoneNumber> PNumber
{
get { return pNumber; }
}
public string Name
{
get { return name; }
}
//Constructor
public Contact(string _name, List<PhoneNumber> _pNumber,Adress _cAdress)
{
name = _name;
pNumber = _pNumber;
cAdress = _cAdress;
}
public static List<Contact> Get()
{
List<Contact> output = new List<Contact>();
XDocument data = XDocument.Load(fLocation);
var query = from c in data.Descendants("contact")
orderby c.Element("name").Value
select c;
foreach (var item in query)
{
List<PhoneNumber> pNumber = new List<PhoneNumber>();
foreach (var PhoneNumbers in item.Elements("phone"))
{
pNumber.Add(new PhoneNumber(PhoneNumbers.Value,PhoneNumbers.Attribute("type").Value));
}
Adress cAdress = new Adress(item.Element("address").Element("street1").Value,
item.Element("address").Element("city").Value,
item.Element("address").Element("state").Value,
item.Element("address").Element("postal").Value);
output.Add(new Contact(item.Element("name").Value,pNumber,cAdress));
}
return output;
}
//subclasses
public class Adress
{
private string street;
private string city;
private string state;
private string postal;
public string Postal
{
get { return postal; }
}
public string State
{
get { return state; }
}
public string City
{
get { return city; }
}
public string Street
{
get { return street; }
}
public Adress(string _street,string _city, string _state, string _postal)
{
street = _street;
city = _city;
state = _state;
postal = _postal;
}
}
public class PhoneNumber
{
private string number;
private string numberType;
public string NumberType
{
get { return numberType; }
}
public string Number
{
get { return number; }
}
public PhoneNumber(string _number, string _phoneNumberType)
{
number = _number;
numberType = _phoneNumberType;
}
}
}
And I want to somehow bind to Gridview:
(default.aspx)
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataSourceID="ObjectDataSource1">
<Columns>
<asp:BoundField DataField="Name" HeaderText="Name" ReadOnly="True"
SortExpression="Name" />
<asp:DynamicField DataField="CAdress" HeaderText="CAdress" />
<asp:DynamicField DataField="PNumber" HeaderText="PNumber" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="Get"
TypeName="LINQtoXML_WebForms.Contact"></asp:ObjectDataSource>
Any ideas how to bind for example Contact.PhoneNumber.number + "-" Contact.PhoneNumber.numberType to colomn?
i.e.: 774-6655-252 - mobile
Thanks.
When I run it, it shows me an error:
Could not determine a MetaTable. A MetaTable could not be determined for the data source 'ObjectDataSource1' and one could not be inferred from the request URL. Make sure that the table is mapped to the dats source, or that the data source is configured with a valid context type and table name, or that the request is part of a registered DynamicDataRoute.
I think you either have to add meta information to your class or use the approach I'd use - write a method yourself instead of using objectdatasource object.
For example Linq to XML
public List<Contact> GetContacts()
{
XDocument doc = XDocument.Load("path_to_some_file.xml");
var contacts = from o in doc.Descendants("contact")
select new Contact()
{
Name = (string)o.Element("Name"),
Phone = (string)o.Element("Phone")
};
return contacts.ToList();
}
and then just bind it in code-behind to your control:
GridView1.DataSource = GetContacts();
GridView1.DataBind();
Hope you get the idea.

ASP.NET MVC3: Interaction between Partial View and Main View

I have a partial view for contact. Currently the index view shows this partial view for contact details. There is a save button inside the partial view to save the edited data. There is a validation for age while saving the edited data. This much is working fine.
Whenever user edit age and save it, I need to show the corresponding horoscope prediction on the main view. How do we achieve it?
public class ContactEntity
{
public int ContactID { get; set; }
public string ContactName { get; set; }
[Range(18, 50, ErrorMessage = "Must be between 18 and 50")]
public int ContactAge { get; set; }
}
public class AgeHoroscope
{
public int Age { get; set; }
public string HoroscopePrediction { get; set; }
}
//Home Controller
namespace MYContactEditPartialViewTEST.Controllers
{
public class HomeController : Controller
{
List<AgeHoroscope> horoList = new List<AgeHoroscope>()
{
new AgeHoroscope{Age=16,HoroscopePrediction="You are confused"},
new AgeHoroscope{Age=26,HoroscopePrediction="You are very brilliant"},
new AgeHoroscope{Age=27,HoroscopePrediction="You are practical"}
};
public ActionResult Index()
{
AgeHoroscope selectedHoro = horoList[1];
return View(selectedHoro);
}
}
}
//Contact Controller
namespace MYContactEditPartialViewTEST.Controllers
{
public class ContactController : Controller
{
public PartialViewResult MyContactDetailEdit()
{
Thread.Sleep(500);
return PartialView(GetContact());
}
[HttpPost]
public PartialViewResult MyContactDetailEdit(string conatcclick)
{
//Save to database
Thread.Sleep(500);
return PartialView(GetContact());
}
private ContactEntity GetContact()
{
ContactEntity contactEntity = new ContactEntity();
contactEntity.ContactID = 1;
contactEntity.ContactName = "Lijo";
contactEntity.ContactAge = 26;
return contactEntity;
}
}
}
//Index.cshtml
#model MYContactEditPartialViewTEST.AgeHoroscope
#{
ViewBag.Title = "Index";
}
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"> </script>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<h2>
Index</h2>
<div>
<a>Your age is <b>#Html.DisplayFor(x => x.Age) </b>and the prediction is <b>" #Html.DisplayFor(x => x.HoroscopePrediction)
" </b></a>
<br />
</div>
<div style="border: 3px solid Teal">
#Html.Action("MyContactDetailEdit", "contact")
</div>
// MyContactDetailEdit.cshtml
#model MYContactEditPartialViewTEST.ContactEntity
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<h3>MyContactDetailEdit PARTIAL</h3>
<div>
#Html.HiddenFor(x => x.ContactID)
<br />
<div style="font-weight:bold">
Name:
<br />
</div>
#Html.DisplayFor(x => x.ContactName)
<br />
<br />
<div style="font-weight:bold">
Age
<br />
</div>
#Html.EditorFor(x => x.ContactAge)
#Html.ValidationMessageFor(model => model.ContactAge)
<br />
<br />
</div>
<input type="submit" id="saveButton" value="Save" />
}
READING
ASP.Net MVC Passing multiple parameters to a view
ASP.Net MVC 3 RC2, Partial Views Form Handling
I would like just use jQuery to do ajax post and then change the parent view client side directly
you'll need to create a new ViewModel to do this. This ViewModel (IndexViewModel.cs) would look something like this (I'm guessing at this):
public class IndexViewModel
{
public int ContactID { get; set; }
public string ContactName { get; set; }
public int ContactAge { get; set; }
public string HoroscopePrediction { get; set; }
}
you'd then use it in your controller index action (and view):
#model MYContactEditPartialViewTEST.IndexViewModel
the idea being that you'd populate the HoroscopePrediction in a join between ContactEntity and AgeHoroscope (or via Linq etc) and thus show each line in the index as a complete object (showing contact and horoscope).
As data is posted to "HomeController" and "Index" action, so changes are reflected when you change age in View.
Try to modify the home controller as follows,then it will work as expected.
1) Instead of having a list of AgeHoroscope, we can have a dictionary of age and prediction.
2) Create two Index Action for HttpGet and HttpPost as follows.
public class HomeController : Controller
{
Dictionary<int, string> AgePred = new Dictionary<int, string>()
{
{16,"You are confused"},
{26,"You are very brilliant"},
{27,"You are practical"}
};
[HttpGet]
public ActionResult Index()
{
AgeHoroscope selectedHoro = new AgeHoroscope() { Age = 26 };
selectedHoro.HoroscopePrediction = AgePred[selectedHoro.Age];
return View(selectedHoro);
}
[HttpPost]
public ActionResult Index(AgeHoroscope model,ContactEntity entity)
{
model.Age = entity.ContactAge;
model.HoroscopePrediction = AgePred[entity.ContactAge];
return View(model);
}
}

Resources