Blazorise DataGrid: Dynamic Data Binding
The Blazorise DataGrid component offers the ability to bind to dynamic data, providing enhanced flexibility for various applications.
Basic Example
To ensure theDataGrid correctly interprets the structure and type of your dynamic data during specific operations, such as creating new items or aggregating data, you need to define a representation within the NewItemCreator function. Below is an illustrative example.
@using System @using System.Collections.Generic @using System.ComponentModel.DataAnnotations @using System.Linq @using System.Threading.Tasks @using System.Dynamic <DataGrid TItem="ExpandoObject" Data="inMemoryData" Responsive ShowPager ShowPageSizes PageSize="5" Editable EditMode="DataGridEditMode.Inline" NewItemCreator="NewItemCreator"> <DataGridAggregates> <DataGridAggregate Field="Email" Aggregate="DataGridAggregateType.Count"> <DisplayTemplate> @($"Total emails: {context.Value}") </DisplayTemplate> </DataGridAggregate> <DataGridAggregate Field="Salary" Aggregate="DataGridAggregateType.Sum" DisplayFormat="{0:C}" DisplayFormatProvider="@System.Globalization.CultureInfo.GetCultureInfo( "fr-FR" )" /> <DataGridAggregate Field="IsActive" Aggregate="DataGridAggregateType.TrueCount" /> <DataGridAggregate Field="Childrens" Aggregate="DataGridAggregateType.Sum" /> </DataGridAggregates> <DataGridColumns> <DataGridCommandColumn></DataGridCommandColumn> <DataGridColumn Editable TextAlignment="TextAlignment.Center" Field="@nameof( Employee.Id )" Caption="#" Width="Width.Px( 60 )" /> <DataGridColumn Editable Field="FirstName" Caption="First Name"> </DataGridColumn> <DataGridColumn Editable Field="LastName" Caption="Last Name" /> <DataGridColumn Editable Field="Email" Caption="Email" /> <DataGridColumn Editable Field="City" Caption="City"> <CaptionTemplate> <Icon Name="IconName.City" /> @context.Caption </CaptionTemplate> </DataGridColumn> <DataGridColumn Editable Field="Zip" Caption="Zip"> </DataGridColumn> <DataGridDateColumn Field="DateOfBirth" DisplayFormat="{0:dd.MM.yyyy}" Caption="Birth Date" Editable /> <DataGridNumericColumn Field="Childrens" Caption="Childrens" ReverseSorting="true" Editable Filterable="false" /> <DataGridSelectColumn Field="Gender" Caption="Gender" Editable Data="EmployeeData.Genders" ValueField="( x ) => ( (Gender)x ).Code" TextField="( x ) => ( (Gender)x ).Description" /> <DataGridColumn Field="Salary" Caption="Salary" Editable Width="Width.Px( 140 )" DisplayFormat="{0:C}" DisplayFormatProvider="@System.Globalization.CultureInfo.GetCultureInfo( "fr-FR" )" TextAlignment="TextAlignment.End"> </DataGridColumn> <DataGridCheckColumn Field="IsActive" Caption="Active" Editable Filterable="false"> <DisplayTemplate> <Check TValue="bool" Value="@(((dynamic)context.Item).IsActive)" Disabled ReadOnly /> </DisplayTemplate> </DataGridCheckColumn> </DataGridColumns> </DataGrid>
@code { private readonly EmployeeData EmployeeData = new(); private List<ExpandoObject> inMemoryData; protected override async Task OnInitializedAsync() { inMemoryData = new(); var data = ( await EmployeeData.GetDataAsync().ConfigureAwait( false ) ).Take( 25 ); foreach ( var item in data ) { IDictionary<string, object> expando = new ExpandoObject(); foreach ( var property in typeof( Employee ).GetProperties() ) { expando.Add( property.Name, property.GetValue( item ) ); } inMemoryData.Add( (ExpandoObject)expando ); } await base.OnInitializedAsync(); } private ExpandoObject NewItemCreator() { IDictionary<string, object> expando = new ExpandoObject(); foreach ( var property in typeof( Employee ).GetProperties() ) { expando.Add( property.Name, property.PropertyType.IsValueType ? Activator.CreateInstance( property.PropertyType ) : null ); } return (ExpandoObject)expando; } public class Gender { public string Code { get; set; } public string Description { get; set; } } public class EmployeeData { private static readonly string[] FirstNames = ["Samuel", "Irvin", "Cora", "Jessie", "Maryann", "Kara"]; private static readonly string[] LastNames = ["Collier", "Ziemann", "Conn", "Wilkinson", "Hilpert", "Brekke"]; private static readonly string[] Cities = ["London", "Paris", "New York", "Berlin", "Lisbon", "Zagreb"]; public static IEnumerable<Gender> Genders = [ new() { Code = null, Description = string.Empty }, new() { Code = "M", Description = "Male" }, new() { Code = "F", Description = "Female" }, new() { Code = "D", Description = "Diverse" } ]; public Task<List<Employee>> GetDataAsync() => Task.FromResult( Enumerable.Range( 1, 500 ) .Select( index => { string firstName = FirstNames[( index - 1 ) % FirstNames.Length]; string lastName = LastNames[( index - 1 ) % LastNames.Length]; return new Employee { Id = index, FirstName = firstName, LastName = lastName, Email = $"{firstName}.{lastName}{index}@example.com", City = Cities[( index - 1 ) % Cities.Length], Zip = $"{10000 + index}", DateOfBirth = new DateTime( 1950 + index % 50, 1 + index % 12, 1 + index % 28 ), Childrens = index % 6, Gender = index % 3 == 0 ? "D" : index % 2 == 0 ? "F" : "M", Salary = 50000m + index * 137m % 50000m, IsActive = index % 2 == 0, Salaries = Enumerable.Range( 1, index % 4 ) .Select( month => new Salary { Date = new DateTime( 2025, month, 1 ), Total = 1000m + index * month * 11m } ) .ToList() }; } ) .ToList() ); } public class Employee { public Employee() { } public Employee( Employee other ) { Id = other.Id; Childrens = other.Childrens; DateOfBirth = other.DateOfBirth; City = other.City; Email = other.Email; FirstName = other.FirstName; LastName = other.LastName; Gender = other.Gender; IsActive = other.IsActive; Salaries = other.Salaries; Salary = other.Salary; Tax = other.Tax; Zip = other.Zip; } [Display( Name = "Id" )] public int Id { get; set; } [Required] public string FirstName { get; set; } [Required] public string LastName { get; set; } [Required] [EmailAddress] [Display( Name = "Email" )] public string Email { get; set; } [Display( Name = "City" )] public string City { get; set; } [Display( Name = "Zip" )] public string Zip { get; set; } [Display( Name = "DOB" )] public DateTime? DateOfBirth { get; set; } [Display( Name = "Childrens" )] public int? Childrens { get; set; } [Display( Name = "Gender" )] public string Gender { get; set; } [Display( Name = "Salary" )] public decimal Salary { get; set; } [Display( Name = "Tax" )] public decimal Tax { get { if ( tax == 0 && Salary > 0 ) { tax = Salary * TaxPercentage; } return tax; } set { tax = value; } } [Display( Name = "Active" )] public bool IsActive { get; set; } public List<Salary> Salaries { get; set; } = new(); public decimal ChildrensPerSalary => Salary == 0m ? 0m : ( Childrens is null || Childrens == 0 ? 1 : Childrens.Value ) / Salary; public decimal TaxPercentage = 0.25m; private decimal tax; } public class Salary { public DateTime Date { get; set; } public decimal Total { get; set; } } }
Auto Generate Columns Example
The Blazorise DataGrid also supports auto-generating columns based on the data structure. This feature simplifies the process of displaying data by automatically creating columns that match the properties of the bound data objects.
Auto-generated columns support nullable data. If your data includes null values, ensure you provide a NewItemCreator. DataGrid requires an item with non-null values to properly generate the columns.
@using System @using System.Collections.Generic @using System.ComponentModel.DataAnnotations @using System.Linq @using System.Threading.Tasks @using System.Dynamic <DataGrid TItem="ExpandoObject" Data="inMemoryData" Responsive ShowPager ShowPageSizes PageSize="5" Editable EditMode="DataGridEditMode.Inline" NewItemCreator="NewItemCreator" />
@code { private readonly EmployeeData EmployeeData = new(); private List<ExpandoObject> inMemoryData; protected override async Task OnInitializedAsync() { inMemoryData = new(); var data = ( await EmployeeData.GetDataAsync().ConfigureAwait( false ) ).Take( 25 ); foreach ( var item in data ) { IDictionary<string, object> expando = new ExpandoObject(); foreach ( var property in typeof( Employee ).GetProperties() ) { expando.Add( property.Name, property.GetValue( item ) ); } inMemoryData.Add( (ExpandoObject)expando ); } await base.OnInitializedAsync(); } private ExpandoObject NewItemCreator() { IDictionary<string, object> expando = new ExpandoObject(); foreach ( var property in typeof( Employee ).GetProperties() ) { expando.Add( property.Name, property.PropertyType switch { { } t when t == typeof( string ) => "", { IsValueType: true } => Activator.CreateInstance( property.PropertyType ) ?? "", _ => "" //better than null } ); } return (ExpandoObject)expando; } public class Gender { public string Code { get; set; } public string Description { get; set; } } public class EmployeeData { private static readonly string[] FirstNames = ["Samuel", "Irvin", "Cora", "Jessie", "Maryann", "Kara"]; private static readonly string[] LastNames = ["Collier", "Ziemann", "Conn", "Wilkinson", "Hilpert", "Brekke"]; private static readonly string[] Cities = ["London", "Paris", "New York", "Berlin", "Lisbon", "Zagreb"]; public static IEnumerable<Gender> Genders = [ new() { Code = null, Description = string.Empty }, new() { Code = "M", Description = "Male" }, new() { Code = "F", Description = "Female" }, new() { Code = "D", Description = "Diverse" } ]; public Task<List<Employee>> GetDataAsync() => Task.FromResult( Enumerable.Range( 1, 500 ) .Select( index => { string firstName = FirstNames[( index - 1 ) % FirstNames.Length]; string lastName = LastNames[( index - 1 ) % LastNames.Length]; return new Employee { Id = index, FirstName = firstName, LastName = lastName, Email = $"{firstName}.{lastName}{index}@example.com", City = Cities[( index - 1 ) % Cities.Length], Zip = $"{10000 + index}", DateOfBirth = new DateTime( 1950 + index % 50, 1 + index % 12, 1 + index % 28 ), Childrens = index % 6, Gender = index % 3 == 0 ? "D" : index % 2 == 0 ? "F" : "M", Salary = 50000m + index * 137m % 50000m, IsActive = index % 2 == 0, Salaries = Enumerable.Range( 1, index % 4 ) .Select( month => new Salary { Date = new DateTime( 2025, month, 1 ), Total = 1000m + index * month * 11m } ) .ToList() }; } ) .ToList() ); } public class Employee { public Employee() { } public Employee( Employee other ) { Id = other.Id; Childrens = other.Childrens; DateOfBirth = other.DateOfBirth; City = other.City; Email = other.Email; FirstName = other.FirstName; LastName = other.LastName; Gender = other.Gender; IsActive = other.IsActive; Salaries = other.Salaries; Salary = other.Salary; Tax = other.Tax; Zip = other.Zip; } [Display( Name = "Id" )] public int Id { get; set; } [Required] public string FirstName { get; set; } [Required] public string LastName { get; set; } [Required] [EmailAddress] [Display( Name = "Email" )] public string Email { get; set; } [Display( Name = "City" )] public string City { get; set; } [Display( Name = "Zip" )] public string Zip { get; set; } [Display( Name = "DOB" )] public DateTime? DateOfBirth { get; set; } [Display( Name = "Childrens" )] public int? Childrens { get; set; } [Display( Name = "Gender" )] public string Gender { get; set; } [Display( Name = "Salary" )] public decimal Salary { get; set; } [Display( Name = "Tax" )] public decimal Tax { get { if ( tax == 0 && Salary > 0 ) { tax = Salary * TaxPercentage; } return tax; } set { tax = value; } } [Display( Name = "Active" )] public bool IsActive { get; set; } public List<Salary> Salaries { get; set; } = new(); public decimal ChildrensPerSalary => Salary == 0m ? 0m : ( Childrens is null || Childrens == 0 ? 1 : Childrens.Value ) / Salary; public decimal TaxPercentage = 0.25m; private decimal tax; } public class Salary { public DateTime Date { get; set; } public decimal Total { get; set; } } }
API
See the documentation below for a complete reference to all of the props and classes available to the components mentioned here.