Default Data Grid
The <MudDataGrid>
is used to display and work with small amounts of data up to very large datasets, easily and efficiently. In its
simplest form, the data grid is just a table, displaying data from a data source. In its most complex form, the data grid allows filtering, editing, grouping, and much more.
Using the data grid is pretty simple to start with and just requires setting the Items
property to a collection of data as IEnumerable, and adding
Columns
.
Nr | Sign | Name | Position | Molar mass |
---|---|---|---|---|
1 | H | Hydrogen | 0 | 1.00794 |
2 | He | Helium | 17 | 4.002602 |
3 | Li | Lithium | 0 | 6.941 |
4 | Be | Beryllium | 1 | 9.012182 |
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid Items="@Elements.Take(4)"> <Columns> <PropertyColumn Property="x => x.Number" Title="Nr" /> <PropertyColumn Property="x => x.Sign" /> <PropertyColumn Property="x => x.Name" /> <PropertyColumn Property="x => x.Position" /> <PropertyColumn Property="x => x.Molar" Title="Molar mass" /> </Columns> </MudDataGrid>
@code { private IEnumerable<Element> Elements = new List<Element>(); protected override async Task OnInitializedAsync() { Elements = await httpClient.GetFromJsonAsync<List<Element>>("webapi/periodictable"); } }
Column Types
There are two main column types: <PropertyColumn>
and <TemplateColumn>
. PropertyColumns
are typically used to display a single property defined by the parameter, Property
.
You would use TemplateColumns when you want to display a column without linking it directly to a property in the data source. For example, if you
wanted to show a column that has action buttons. TemplateColumn cannot infer things such as Title and SortBy like the PropertyColumn.
You can pass a format string in the Format
parameter on PropertyColumn to format the value for the cells.
Name | Position | Years Employed | Salary | Total Earned | |
---|---|---|---|---|---|
Sam | CPA | 23 | $87,000.00 | $2,001,000.00 | |
Alicia | Product Manager | 11 | $143,000.00 | $1,573,000.00 | |
Ira | Developer | 4 | $92,000.00 | $368,000.00 | |
John | IT Director | 17 | $229,000.00 | $3,893,000.00 | |
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid Items="" Filterable="false" SortMode="@SortMode.None" Groupable="false"> <Columns> <PropertyColumn Property="x => x.Name" /> <PropertyColumn Property="x => x.Position" /> <PropertyColumn Property="x => x.YearsEmployed" Title="Years Employed" /> <PropertyColumn Property="x => x.Salary" Format="C" /> <PropertyColumn Property="x => x.Salary * x.YearsEmployed" Title="Total Earned" Format="C" /> <TemplateColumn CellClass="d-flex justify-end"> <CellTemplate> <MudStack Row> <MudRating Size="@Size.Small" SelectedValue="@context.Item.Rating" /> <MudButton Size="@Size.Small" Variant="@Variant.Filled" Color="@Color.Primary">Hire</MudButton> </MudStack> </CellTemplate> </TemplateColumn> </Columns> </MudDataGrid>
@code { public record Employee(string Name, string Position, int YearsEmployed, int Salary, int Rating); public IEnumerable<Employee> employees; protected override void OnInitialized() { employees = new List<Employee> { new Employee("Sam", "CPA", 23, 87_000, 4), new Employee("Alicia", "Product Manager", 11, 143_000, 5), new Employee("Ira", "Developer", 4, 92_000, 3), new Employee("John", "IT Director", 17, 229_000, 4), }; } }
Advanced Data Grid
In a more advanced scenario, the data grid offers sorting, filtering, pagination and selection. There are two ways to filter the data
fed into the data grid. A QuickFilter
function allows filtering the items in the grid globally. Data can also be filtered by specifying
column filters, enabling a more robust filtration.
In this example, we turn sorting and filtering off for the Nr column using the boolean Sortable
and Filterable
properties
as well as hide the column options icon button by setting the ShowColumnOptions
property to false
(which is hidden by default). Additionally, we
can override the default SortBy
function for each column, seen in the Name column where we show how you can switch to a sort by the Name's length.
To hide the filter icons unless a column is currently filtered, you can set the ShowFilterIcons
property to false.
| Nr | Sign | Name | Position | Molar mass | Category |
---|---|---|---|---|---|---|
1 | H | Hydrogen | 0 | 1.00794 | Other | |
2 | He | Helium | 17 | 4.002602 | Noble Gas (p) | |
3 | Li | Lithium | 0 | 6.941 | Alkaline Earth Metal (s) | |
4 | Be | Beryllium | 1 | 9.012182 | Alkaline Metal (s) | |
5 | B | Boron | 12 | 10.811 | Metalloid Boron (p) | |
6 | C | Carbon | 13 | 12.0107 | Nonmetal Carbon (p) | |
7 | N | Nitrogen | 14 | 14.0067 | Nonmetal Pnictogen (p) | |
8 | O | Oxygen | 15 | 15.9994 | Nonmetal Chalcogen (p) | |
9 | F | Fluorine | 16 | 18.998404 | Halogen (p) | |
10 | Ne | Neon | 17 | 20.1797 | Noble Gas (p) | |
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid T="Element" MultiSelection="true" Items="" SortMode="SortMode.Multiple" Filterable="true" QuickFilter="@_quickFilter" Hideable="true" RowClick="" RowContextMenuClick="RowRightClicked" SelectedItemsChanged=""> <ToolBarContent> <MudText Typo="Typo.h6">Periodic Elements</MudText> <MudSpacer /> <MudTextField @bind-Value="_searchString" Placeholder="Search" Adornment="Adornment.Start" Immediate="true" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"></MudTextField> </ToolBarContent> <Columns> <SelectColumn T="Element" /> <PropertyColumn Property="x => x.Number" Title="Nr" Sortable="false" Filterable="false" /> <PropertyColumn Property="x => x.Sign" /> <PropertyColumn Property="x => x.Name" SortBy="@_sortBy" /> <PropertyColumn Property="x => x.Position" /> <PropertyColumn Property="x => x.Molar" Title="Molar mass" /> <PropertyColumn Property="x => x.Group" Title="Category" /> </Columns> <PagerContent> <MudDataGridPager T="Element" /> </PagerContent> </MudDataGrid> <div class="d-flex flex-wrap mt-4"> <MudSwitch @bind-Value="@_sortNameByLength" Color="Color.Primary">Sort Name Column By Length</MudSwitch> </div> <MudExpansionPanels Style="flex:1"> <MudExpansionPanel Text="Show Events"> @foreach (var message in _events) { <MudText Typo="@Typo.body2">@message</MudText> } @if(_events.Count > 0) { <div class="d-flex"> <MudSpacer/> <MudButton Class="mt-3" ButtonType="ButtonType.Button" Variant="Variant.Filled" OnClick="@(() => _events.Clear())">Clear</MudButton> </div> } </MudExpansionPanel> </MudExpansionPanels>
@code { private IEnumerable<Element> Elements = new List<Element>(); private string _searchString; private bool _sortNameByLength; private List<string> _events = new(); // custom sort by name length private Func<Element, object> _sortBy => x => { if (_sortNameByLength) return x.Name.Length; else return x.Name; }; // quick filter - filter globally across multiple columns with the same input private Func<Element, bool> _quickFilter => x => { if (string.IsNullOrWhiteSpace(_searchString)) return true; if (x.Sign.Contains(_searchString, StringComparison.OrdinalIgnoreCase)) return true; if (x.Name.Contains(_searchString, StringComparison.OrdinalIgnoreCase)) return true; if ($"{x.Number} {x.Position} {x.Molar}".Contains(_searchString)) return true; return false; }; protected override async Task OnInitializedAsync() { Elements = await httpClient.GetFromJsonAsync<List<Element>>("webapi/periodictable"); } // events void RowClicked(DataGridRowClickEventArgs<Element> args) { _events.Insert(0, $"Event = RowClick, Index = {args.RowIndex}, Data = {System.Text.Json.JsonSerializer.Serialize(args.Item)}"); } void RowRightClicked(DataGridRowClickEventArgs<Element> args) { _events.Insert(0, $"Event = RowRightClick, Index = {args.RowIndex}, Data = {System.Text.Json.JsonSerializer.Serialize(args.Item)}"); } void SelectedItemsChanged(HashSet<Element> items) { _events.Insert(0, $"Event = SelectedItemsChanged, Data = {System.Text.Json.JsonSerializer.Serialize(items)}"); } }
Visual Styling
The <MudDataGrid>
has many built in properties to change its style and also allows for custom styling as well.
Row level classes and styles can be applied using the RowClass
and RowStyle
properties
respectively. To style rows according to the data of the row, you would use the RowClassFunc
and RowStyleFunc
properties. For even finer grain control, you can style at the header, cell and footer level as well by using the HeaderClass
, HeaderStyle
,
HeaderClassFunc
, HeaderStyleFunc
, CellClass
,
CellStyle
, CellClassFunc
, CellStyleFunc
,
FooterClass
, FooterStyle
, FooterClassFunc
and FooterStyleFunc
properties.
Nr | Sign | Name | Position | Molar mass |
---|---|---|---|---|
1 | H | Hydrogen | 0 | 1.00794 |
2 | He | Helium | 17 | 4.002602 |
3 | Li | Lithium | 0 | 6.941 |
4 | Be | Beryllium | 1 | 9.012182 |
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid Items="@Elements.Take(4)" Hover="@_hover" Dense="@_dense" Striped="@_striped" Bordered="@_bordered" RowStyleFunc="@_rowStyleFunc"> <Columns> <PropertyColumn Property="x => x.Number" Title="Nr" /> <PropertyColumn Property="x => x.Sign" /> <PropertyColumn Property="x => x.Name" CellStyleFunc="@_cellStyleFunc" /> <PropertyColumn Property="x => x.Position" /> <PropertyColumn Property="x => x.Molar" Title="Molar mass" /> </Columns> </MudDataGrid> <div class="d-flex flex-wrap mt-4"> <MudSwitch @bind-Value="_hover" Color="Color.Primary">Hover</MudSwitch> <MudSwitch @bind-Value="_dense" Color="Color.Secondary">Dense</MudSwitch> <MudSwitch @bind-Value="_striped" Color="Color.Tertiary">Striped</MudSwitch> <MudSwitch @bind-Value="_bordered" Color="Color.Warning">Bordered</MudSwitch> </div>
@code { private IEnumerable<Element> Elements = new List<Element>(); private bool _hover; private bool _dense; private bool _striped; private bool _bordered; // style the rows where the Element.Position == 0 to have italic text. private Func<Element, int, string> _rowStyleFunc => (x, i) => { if (x.Position == 0) return "font-style:italic"; return ""; }; // style the cells according to the element's physical classification and the molar mass. private Func<Element, string> _cellStyleFunc => x => { string style = ""; if (x.Number == 1) style += "background-color:#8CED8C"; else if (x.Number == 2) style += "background-color:#E5BDE5"; else if (x.Number == 3) style += "background-color:#EACE5D"; else if (x.Number == 4) style += "background-color:#F1F165"; if (x.Molar > 5) style += ";font-weight:bold"; return style; }; protected override async Task OnInitializedAsync() { Elements = await httpClient.GetFromJsonAsync<List<Element>>("webapi/periodictable"); } }
Editing
The <MudDataGrid>
allows editing the data passed into it. Setting the ReadOnly
property
to false
and the EditMode
property to DataGridEditMode.Form
or to DataGridEditMode.Cell
turns on editing. Edit mode Form
displays a form in a popup
when editing. Edit mode Cell
is more like Excel where each cell is ready to edit and as you make edits, they are
applied to the data source. To disable editing on a column, set its IsEditable
property to false
.
To mark a property as not required, set its Required
property to false
.
By default, the built-in editing in the data grid automatically supplies the proper input component for each cell. However, this can be overridden
by supplying an <EditTemplate>
. Inside the template, you have full control over the editing. Take a look at the Position
column below.
Nr | Sign | Name | Position | Molar mass | |
---|---|---|---|---|---|
1 | H | Hydrogen | 0 | 1.00794 | |
2 | He | Helium | 17 | 4.002602 | |
3 | Li | Lithium | 0 | 6.941 | |
4 | Be | Beryllium | 1 | 9.012182 | |
Form
Manual
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid T="Element" Items="@Elements.Take(4)" ReadOnly="@_readOnly" EditMode="@(_isCellEditMode ? DataGridEditMode.Cell : DataGridEditMode.Form)" StartedEditingItem="" CanceledEditingItem="" CommittedItemChanges="" Bordered="true" Dense="true" EditTrigger="@(_editTriggerRowClick ? DataGridEditTrigger.OnRowClick : DataGridEditTrigger.Manual)"> <Columns> <PropertyColumn Property="x => x.Number" Title="Nr" Editable="false" /> <PropertyColumn Property="x => x.Sign" /> <PropertyColumn Property="x => x.Name" /> <PropertyColumn Property="x => x.Position"> <EditTemplate> <MudSelect @bind-Value="context.Item.Position" Required RequiredError="You must select a Position!!!" Margin="@Margin.Dense"> <MudSelectItem Value="0">zero</MudSelectItem> <MudSelectItem Value="1">one</MudSelectItem> <MudSelectItem Value="17">seventeen</MudSelectItem> </MudSelect> </EditTemplate> </PropertyColumn> <PropertyColumn Property="x => x.Molar" Title="Molar mass" /> <TemplateColumn Hidden="@(_isCellEditMode || _readOnly || _editTriggerRowClick)" CellClass="d-flex justify-end"> <CellTemplate> <MudIconButton Size="@Size.Small" Icon="@Icons.Material.Outlined.Edit" OnClick="@context.Actions.StartEditingItemAsync" /> </CellTemplate> </TemplateColumn> </Columns> </MudDataGrid> <div class="d-flex flex-wrap mt-4"> <MudSwitch @bind-Value="_readOnly" Color="Color.Primary">Read Only</MudSwitch> <div class="d-flex justify-start align-center"> <p class="mud-typography mud-typography-body1 mud-inherit-text mr-2">Form</p> <MudSwitch @bind-Value="_isCellEditMode" Color="Color.Primary">Cell</MudSwitch> </div> <div class="d-flex justify-start align-center"> <p class="mud-typography mud-typography-body1 mud-inherit-text mr-2">Manual</p> <MudSwitch @bind-Value="_editTriggerRowClick" Color="Color.Primary">On Row Click</MudSwitch> </div> </div> <MudExpansionPanels Style="flex:1"> <MudExpansionPanel Text="Show Events"> @foreach (var message in _events) { <MudText Typo="@Typo.body2">@message</MudText> } @if(_events.Count > 0) { <div class="d-flex"> <MudSpacer/> <MudButton Class="mt-3" ButtonType="ButtonType.Button" Variant="Variant.Filled" OnClick="@(() => _events.Clear())">Clear</MudButton> </div> } </MudExpansionPanel> </MudExpansionPanels>
@code { private IEnumerable<Element> Elements = new List<Element>(); private bool _readOnly; private bool _isCellEditMode; private List<string> _events = new(); private bool _editTriggerRowClick; protected override async Task OnInitializedAsync() { Elements = await httpClient.GetFromJsonAsync<List<Element>>("webapi/periodictable"); } // events void StartedEditingItem(Element item) { _events.Insert(0, $"Event = StartedEditingItem, Data = {System.Text.Json.JsonSerializer.Serialize(item)}"); } void CanceledEditingItem(Element item) { _events.Insert(0, $"Event = CanceledEditingItem, Data = {System.Text.Json.JsonSerializer.Serialize(item)}"); } void CommittedItemChanges(Element item) { _events.Insert(0, $"Event = CommittedItemChanges, Data = {System.Text.Json.JsonSerializer.Serialize(item)}"); } }
Grouping
The <MudDataGrid>
allows you to group data by column. Setting the Grouping
property
to true
will turn on grouping which will add a menu item in the column options to toggle grouping of that column.
To disable grouping on a column, set its Groupable
property to false
.
Nr | Sign | Name | Position | Molar mass | Category | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Category: Other | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Category: Noble Gas (p) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Category: Alkaline Earth Metal (s) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Category: Alkaline Metal (s) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Category: Metalloid Boron (p) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Category: Nonmetal Carbon (p) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Category: Nonmetal Pnictogen (p) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Category: Nonmetal Chalcogen (p) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Category: Halogen (p) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid @ref="dataGrid" MultiSelection="true" Items="" Filterable="true" Hideable="true" Groupable="true" GroupExpanded="false" GroupClassFunc="GroupClassFunc"> <ToolBarContent> <MudText Typo="Typo.h6">Periodic Elements</MudText> <MudSpacer /> </ToolBarContent> <Columns> <PropertyColumn Property="x => x.Number" Title="Nr" Filterable="false" Groupable="false" /> <PropertyColumn Property="x => x.Sign" /> <PropertyColumn Property="x => x.Name" /> <PropertyColumn Property="x => x.Position" /> <PropertyColumn Property="x => x.Molar" Title="Molar mass" /> <PropertyColumn Property="x => x.Group" Title="Category" Grouping GroupBy="@_groupBy"> <GroupTemplate> @if (_customizeGroupTemplate) { <span style="font-weight:bold">Group: @context.Grouping.Key <MudChip Variant="Variant.Outlined" Color="Color.Primary" Size="Size.Small">total @context.Grouping.Count()</MudChip></span> } else { <span style="font-weight:bold">Category: @context.Grouping.Key</span> } </GroupTemplate> </PropertyColumn> </Columns> <PagerContent> <MudDataGridPager T="Element" /> </PagerContent> </MudDataGrid> <div class="d-flex flex-wrap mt-4"> <MudSwitch T="bool" @bind-Value="_customizeGroupTemplate" Color="@Color.Primary">Customize Group Template</MudSwitch> <MudSwitch T="bool" Value="@_customizeGroupBy" Color="@Color.Primary" ValueChanged="">Customize Group By</MudSwitch> <MudButton OnClick="" Color="@Color.Primary">Expand All</MudButton> <MudButton OnClick="" Color="@Color.Primary">Collapse All</MudButton> </div>
@code { IEnumerable<Element> Elements = new List<Element>(); MudDataGrid<Element> dataGrid; bool _customizeGroupTemplate; static bool _customizeGroupBy; static string[] _nonmetals = new string[] { "H", "He","N", "O", "F", "Ne", "Cl", "Ar", "Kr", "Xe", "Rn", "Br", "C", "P", "Se", "Se", "I" }; Func<Element, object> _groupBy = x => { if (_customizeGroupBy) return _nonmetals.Contains(x.Sign) ? "Nonmetal": "Metal"; return x.Group; }; private string GroupClassFunc(GroupDefinition<Element> item) { return item.Grouping.Key?.ToString() == "Nonmetal" || item.Grouping.Key?.ToString() == "Other" ? "mud-theme-warning" : string.Empty; } protected override async Task OnInitializedAsync() { Elements = await httpClient.GetFromJsonAsync<List<Element>>("webapi/periodictable"); } void ExpandAllGroups() { dataGrid?.ExpandAllGroups(); } void CollapseAllGroups() { dataGrid?.CollapseAllGroups(); } void CustomizeByGroupChanged(bool isChecked) { _customizeGroupBy = isChecked; dataGrid.GroupItems(); } }
Sorting
The <MudDataGrid>
allows you to either disable sorting entirely, sort by single column or by multiple columns via
the SortMode
property. The default (SortMode.Multiple
) allows sorting on more than one column (Hold Ctrl-Key
) while clicking
on a header column to extend the sort operation to another column.
Clicking on the column header while Alt-Key
is pressed, will un-sort a column (or remove it from the set of sorted columns) when multiple sorting
is enabled. In the case of multiple sorting, a small index-number next to the sort direction arrow will indicate the order in which columns are sorted.
When mode is set to SortMode.Single
, only a single column can be used for sorting at a time. Using another column for sorting will automatically
un-sort any former sorted column. In single mode, the number indicator next to the direction arrow will not be shown.
In both active modes, single columns can be excluded from sorting by setting the Sortable
property to false for that column.
When SortMode is set to SortMode.None
sorting is disabled globally and setting the Sortable
property on a column has no effect.
You can also use the SortBy
parameter on a TemplateColumn
to allow sorting on that column.
Nr | Sign | Name | Position | Molar mass | Category | Custom |
---|---|---|---|---|---|---|
1 | H | Hydrogen | 0 | 1.00794 | Other | H - Hydrogen |
2 | He | Helium | 17 | 4.002602 | Noble Gas (p) | He - Helium |
3 | Li | Lithium | 0 | 6.941 | Alkaline Earth Metal (s) | Li - Lithium |
4 | Be | Beryllium | 1 | 9.012182 | Alkaline Metal (s) | Be - Beryllium |
5 | B | Boron | 12 | 10.811 | Metalloid Boron (p) | B - Boron |
6 | C | Carbon | 13 | 12.0107 | Nonmetal Carbon (p) | C - Carbon |
7 | N | Nitrogen | 14 | 14.0067 | Nonmetal Pnictogen (p) | N - Nitrogen |
8 | O | Oxygen | 15 | 15.9994 | Nonmetal Chalcogen (p) | O - Oxygen |
9 | F | Fluorine | 16 | 18.998404 | Halogen (p) | F - Fluorine |
10 | Ne | Neon | 17 | 20.1797 | Noble Gas (p) | Ne - Neon |
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid T="Element" Items="" SortMode="@_sortMode"> <Columns> <PropertyColumn Property="x => x.Number" Title="Nr" Sortable="false" /> <PropertyColumn Property="x => x.Sign" /> <PropertyColumn Property="x => x.Name" SortBy="@_sortBy" /> <PropertyColumn Property="x => x.Position" /> <PropertyColumn Property="x => x.Molar" Title="Molar mass" /> <PropertyColumn Property="x => x.Group" Title="Category" /> <TemplateColumn Title="Custom" SortBy="@(x => $"{x.Sign} - {x.Name}")"> <CellTemplate> @context.Item.Sign - @context.Item.Name </CellTemplate> </TemplateColumn> </Columns> <PagerContent> <MudDataGridPager T="Element" /> </PagerContent> </MudDataGrid> <div class="d-flex flex-wrap mt-4"> <MudSwitch @bind-Value="_sortNameByLength" Color="Color.Primary">Sort Name Column By Length</MudSwitch> <MudRadioGroup T=SortMode @bind-Value="@_sortMode"> <MudRadio Dense=true Value=@SortMode.Multiple Color="Color.Primary">Multiple</MudRadio> <MudRadio Dense=true Value=@SortMode.Single Color="Color.Tertiary">Single</MudRadio> <MudRadio Dense=true Value=@SortMode.None>None</MudRadio> </MudRadioGroup> </div>
@code { private IEnumerable<Element> Elements = new List<Element>(); private bool _sortNameByLength; private SortMode _sortMode = SortMode.Multiple; // custom sort by name length private Func<Element, object> _sortBy => x => { if (_sortNameByLength) return x.Name.Length; else return x.Name; }; protected override async Task OnInitializedAsync() { Elements = await httpClient.GetFromJsonAsync<List<Element>>("webapi/periodictable"); } }
Advanced Sorting
The <MudDataGrid>
allows you to provide your own Comparer
for advanced sorting. Keep in mind that the Comparer
will use the same object passed by the SortBy
parameter. If SortBy
is not supplied, it will use the column item for its comparison.
You can also manually call SetSortAsync
on the DataGrid while passing your Comparer
.
Comparer
must implement IComparer<object>
. This example uses a natural sorting algorithm to sort strings with numbers properly.
Name | Value | Misc |
---|---|---|
1 | 42 | 555 |
10 | 73 | 7 |
2 | 11 | 4444 |
1_10 | 33 | 33333 |
1_2 | 99 | 66 |
1_11 | 44 | 1111111 |
0 | 55 | 222222 |
@using System.Globalization; <MudDataGrid @ref="DataGrid" Items="@_items" SortMode="SortMode.Multiple"> <Columns> <PropertyColumn Property="x => x.Name" Comparer="@(NaturalSortingEnabled ? new MudBlazor.Utilities.NaturalComparer() : null)" /> <PropertyColumn Property="x => x.Value" /> <PropertyColumn Property="x => x.Misc" /> </Columns> </MudDataGrid> <MudStack Row="true"> <MudSwitch T="bool" Value="" ValueChanged="OnCheckedChanged" Color="Color.Primary">Enable Natural Sorting</MudSwitch> </MudStack>
@code { private MudDataGrid<Item> DataGrid; private bool NaturalSortingEnabled = true; private IEnumerable<Item> _items = new List<Item>() { new Item("1", 42, "555"), new Item("10", 73, "7"), new Item("2", 11, "4444"), new Item("1_10", 33, "33333"), new Item("1_2", 99, "66"), new Item("1_11", 44, "1111111"), new Item("0", 55, "222222") }; protected override async Task OnAfterRenderAsync(bool firstRender) { await base.OnAfterRenderAsync(firstRender); if (firstRender) { await DataGrid.SetSortAsync(nameof(Item.Name), SortDirection.Ascending, x => x.Name, NaturalSortingEnabled ? new MudBlazor.Utilities.NaturalComparer() : null); } } private async Task OnCheckedChanged(bool value) { NaturalSortingEnabled = value; if (DataGrid.SortDefinitions.ContainsKey(nameof(Item.Name))) { if (DataGrid.SortDefinitions[nameof(Item.Name)].Descending) { DataGrid.SortDefinitions.Clear(); await DataGrid.SetSortAsync(nameof(Item.Name), SortDirection.Descending, x => x.Name, NaturalSortingEnabled ? new MudBlazor.Utilities.NaturalComparer() : null); } else { DataGrid.SortDefinitions.Clear(); await DataGrid.SetSortAsync(nameof(Item.Name), SortDirection.Ascending, x => x.Name, NaturalSortingEnabled ? new MudBlazor.Utilities.NaturalComparer() : null); } } else { await DataGrid.SetSortAsync(nameof(Item.Name), SortDirection.Ascending, x => x.Name, NaturalSortingEnabled ? new MudBlazor.Utilities.NaturalComparer() : null); } } public class Item { public string Name { get; set; } public int Value { get; set; } public string Misc { get; set; } public Item(string name, int value, String misc) { Name = name; Value = value; Misc = misc; } } }
Filtering
The <MudDataGrid>
supports filtering with several different DataGridFilterMode
s by setting the FilterMode
property.
DataGridFilterMode.Simple
is the default where all filters are managed in one popover in the data grid. It allows you to
set multiple filters at one time for multiple different columns. In DataGridFilterMode.ColumnFilterMenu
mode, there is a dedicated popover for
each column. Lastly, DataGridFilterMode.ColumnFilterRow
allows you to inline the filtering behavior directly into the data grid.
Is it possible to define the case sensitivity when filtering string values by setting the parameter FilterCaseSensitivity
.
Nr | Sign | Name | Position | Molar mass | Category |
---|---|---|---|---|---|
1 | H | Hydrogen | 0 | 1.00794 | Other |
2 | He | Helium | 17 | 4.002602 | Noble Gas (p) |
3 | Li | Lithium | 0 | 6.941 | Alkaline Earth Metal (s) |
4 | Be | Beryllium | 1 | 9.012182 | Alkaline Metal (s) |
5 | B | Boron | 12 | 10.811 | Metalloid Boron (p) |
6 | C | Carbon | 13 | 12.0107 | Nonmetal Carbon (p) |
7 | N | Nitrogen | 14 | 14.0067 | Nonmetal Pnictogen (p) |
8 | O | Oxygen | 15 | 15.9994 | Nonmetal Chalcogen (p) |
9 | F | Fluorine | 16 | 18.998404 | Halogen (p) |
10 | Ne | Neon | 17 | 20.1797 | Noble Gas (p) |
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid Items="" Filterable="true" FilterMode="@_filterMode" FilterCaseSensitivity="@_caseSensitivity"> <Columns> <PropertyColumn Property="x => x.Number" Title="Nr" Filterable="false" /> <PropertyColumn Property="x => x.Sign" /> <PropertyColumn Property="x => x.Name" /> <PropertyColumn Property="x => x.Position" Filterable="false" /> <PropertyColumn Property="x => x.Molar" Title="Molar mass" /> <PropertyColumn Property="x => x.Group" Title="Category" /> </Columns> <PagerContent> <MudDataGridPager T="Element" /> </PagerContent> </MudDataGrid> <div class="d-flex flex-wrap mt-4"> <MudRadioGroup T="DataGridFilterMode" @bind-Value="@_filterMode"> <MudRadio Dense="true" Value="@DataGridFilterMode.Simple" Color="Color.Primary">Simple</MudRadio> <MudRadio Dense="true" Value="@DataGridFilterMode.ColumnFilterMenu" Color="Color.Tertiary">Column Menu</MudRadio> <MudRadio Dense="true" Value="@DataGridFilterMode.ColumnFilterRow">Column Row</MudRadio> </MudRadioGroup> </div> <div class="d-flex flex-wrap mt-4"> <MudRadioGroup T="DataGridFilterCaseSensitivity" @bind-Value="@_caseSensitivity"> <MudRadio Dense="true" Value="@DataGridFilterCaseSensitivity.Default" Color="Color.Primary">Default Case Sensitivity</MudRadio> <MudRadio Dense="true" Value="@DataGridFilterCaseSensitivity.CaseInsensitive" Color="Color.Tertiary">Case Insensitive</MudRadio> </MudRadioGroup> </div>
@code { IEnumerable<Element> Elements = new List<Element>(); DataGridFilterMode _filterMode = DataGridFilterMode.Simple; DataGridFilterCaseSensitivity _caseSensitivity = DataGridFilterCaseSensitivity.Default; protected override async Task OnInitializedAsync() { Elements = await httpClient.GetFromJsonAsync<List<Element>>("webapi/periodictable"); } }
Advanced Filtering
It is possible to customize filtering by utilizing the <FilterTemplate>
available on the <MudDataGrid>
as well as each <Column>
. In the example below, the Sign column is customized.
Inside the <FilterTemplate>
on the data grid while using DataGridFilterMode.Simple
, the context is set to the
data grid's FilterDefinitions to allow for customizing the filtering behavior.
When using the <FilterTemplate>
in the column specific filter modes, the context is a DataGridFilterMode.Simple
which gives access to several helpful properties and actions. For example, the current FilterDefinition
related to the column is available as well
as several actions to make it easier to implement custom filter behavior such as ApplyFilter
and ClearFilter
.
Nr | Sign | Name | Position | Molar mass | Category |
---|---|---|---|---|---|
1 | H | Hydrogen | 0 | 1.00794 | Other |
2 | He | Helium | 17 | 4.002602 | Noble Gas (p) |
3 | Li | Lithium | 0 | 6.941 | Alkaline Earth Metal (s) |
4 | Be | Beryllium | 1 | 9.012182 | Alkaline Metal (s) |
5 | B | Boron | 12 | 10.811 | Metalloid Boron (p) |
6 | C | Carbon | 13 | 12.0107 | Nonmetal Carbon (p) |
7 | N | Nitrogen | 14 | 14.0067 | Nonmetal Pnictogen (p) |
8 | O | Oxygen | 15 | 15.9994 | Nonmetal Chalcogen (p) |
9 | F | Fluorine | 16 | 18.998404 | Halogen (p) |
10 | Ne | Neon | 17 | 20.1797 | Noble Gas (p) |
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid T="Element" Items="" Filterable="true" FilterMode="@DataGridFilterMode.ColumnFilterRow"> <Columns> <PropertyColumn Property="x => x.Number" Title="Nr" Filterable="false" /> <PropertyColumn Property="x => x.Sign"> <FilterTemplate> <MudIconButton OnClick="" Icon="@_icon" Size="@Size.Small" /> <MudOverlay Visible="@_filterOpen" OnClick="@(() => _filterOpen = false)" /> <MudPopover Open="@_filterOpen" AnchorOrigin="Origin.BottomCenter" TransformOrigin="Origin.TopCenter" Style="width:150px"> <MudStack Spacing="0"> <MudCheckBox T="bool" Label="Select All" Size="@Size.Small" Value="@_selectAll" ValueChanged="" /> <MudStack Spacing="0" Style="overflow-y:auto;max-height:250px"> @foreach (var item in context.Items) { <MudCheckBox T="bool" Label="@($"{item.Sign}")" Size="@Size.Small" Value="@(_selectedItems.Contains(item))" ValueChanged="@((value) => SelectedChanged(value, item))" /> } </MudStack> <MudStack Row="true"> <MudButton OnClick="@(() => ClearFilterAsync(context))">Clear</MudButton> <MudButton Color="@Color.Primary" OnClick="@(() => ApplyFilterAsync(context))">Filter</MudButton> </MudStack> </MudStack> </MudPopover> </FilterTemplate> </PropertyColumn> <PropertyColumn Property="x => x.Name" /> <PropertyColumn Property="x => x.Position" /> <PropertyColumn Property="x => x.Molar" Title="Molar mass" /> <PropertyColumn Property="x => x.Group" Title="Category" /> </Columns> <PagerContent> <MudDataGridPager T="Element" /> </PagerContent> </MudDataGrid>
@code { IEnumerable<Element> Elements = new List<Element>(); HashSet<Element> _selectedItems = new(); HashSet<Element> _filterItems = new(); FilterDefinition<Element> _filterDefinition; bool _selectAll = true; string _icon = Icons.Material.Outlined.FilterAlt; bool _filterOpen = false; protected override async Task OnInitializedAsync() { Elements = await httpClient.GetFromJsonAsync<List<Element>>("webapi/periodictable"); _selectedItems = Elements.ToHashSet(); _filterItems = Elements.ToHashSet(); _filterDefinition = new FilterDefinition<Element> { FilterFunction = x => _filterItems.Contains(x) }; } void OpenFilter() { _filterOpen = true; } private void SelectedChanged(bool value, Element item) { if (value) _selectedItems.Add(item); else _selectedItems.Remove(item); if (_selectedItems.Count == Elements.Count()) _selectAll = true; else _selectAll = false; } private async Task ClearFilterAsync(FilterContext<Element> context) { _selectedItems = Elements.ToHashSet(); _filterItems = Elements.ToHashSet(); _icon = Icons.Material.Outlined.FilterAlt; await context.Actions.ClearFilterAsync(_filterDefinition); _filterOpen = false; } private async Task ApplyFilterAsync(FilterContext<Element> context) { _filterItems = _selectedItems.ToHashSet(); _icon = _filterItems.Count == Elements.Count() ? Icons.Material.Outlined.FilterAlt : Icons.Material.Filled.FilterAlt; await context.Actions.ApplyFilterAsync(_filterDefinition); _filterOpen = false; } private void SelectAll(bool value) { _selectAll = value; if (value) { _selectedItems = Elements.ToHashSet(); } else { _selectedItems.Clear(); } } }
Row Detail View
The <MudDataGrid>
allows you to create hierarchical layouts. To do that the HierarchyColumn
has to be added in the Columns
definitions.
You can customize the icon to toggle the RowDetail, disable the toggle button and also initially expand the RowDetail.
Nr | Sign | Name | Position | Molar mass | |
---|---|---|---|---|---|
1 | H | Hydrogen | 0 | 1.00794 | |
2 | He | Helium | 17 | 4.002602 | |
3 | Li | Lithium | 0 | 6.941 | |
4 | Be | Beryllium | 1 | 9.012182 | |
5 | B | Boron | 12 | 10.811 | |
6 | C | Carbon | 13 | 12.0107 | |
7 | N | Nitrogen | 14 | 14.0067 | |
8 | O | Oxygen | 15 | 15.9994 | |
9 | F | Fluorine | 16 | 18.998404 | |
10 | Ne | Neon | 17 | 20.1797 | |
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid Items="" ReadOnly="@_isReadOnly" EditMode="@DataGridEditMode.Cell"> <Columns> <HierarchyColumn T="Element" ButtonDisabledFunc="@(x => x.Sign == "He")" InitiallyExpandedFunc="@(x => x.Sign == "Li")" /> <PropertyColumn Property="x => x.Number" Title="Nr" /> <PropertyColumn Property="x => x.Sign" /> <PropertyColumn Property="x => x.Name" /> <PropertyColumn Property="x => x.Position" /> <PropertyColumn Property="x => x.Molar" Title="Molar mass" /> </Columns> <ChildRowContent> <MudCard> <MudCardHeader> <CardHeaderContent> <MudText Typo="Typo.h6">@context.Item.Name</MudText> </CardHeaderContent> </MudCardHeader> <MudCardContent> <MudText>This element is number @context.Item.Number</MudText> <MudText>This element has a molar mass of @context.Item.Molar</MudText> </MudCardContent> </MudCard> </ChildRowContent> <PagerContent> <MudDataGridPager T="Element" /> </PagerContent> </MudDataGrid> <div class="d-flex flex-wrap mt-4"> <MudSwitch T="bool" @bind-Value="_isReadOnly" Color="@Color.Primary">Read Only</MudSwitch> </div>
@code { private IEnumerable<Element> Elements = new List<Element>(); protected override async Task OnInitializedAsync() { Elements = await httpClient.GetFromJsonAsync<List<Element>>("webapi/periodictable"); } private bool _isReadOnly = true; }
Resizing
The <MudDataGrid>
allows you to resize columns interactively when
ColumnResizeMode
is not set to None
, which is the default.
There are two modes for resizing: ResizeMode.Container
and ResizeMode.Column
.
ResizeMode.Container
resizes the entire data grid while ResizeMode.Column
only resizes
columns using available space within the data grid.
Nr | Sign | Name | Position | Molar mass | Category |
---|---|---|---|---|---|
1 | H | Hydrogen | 0 | 1.00794 | Other |
2 | He | Helium | 17 | 4.002602 | Noble Gas (p) |
3 | Li | Lithium | 0 | 6.941 | Alkaline Earth Metal (s) |
4 | Be | Beryllium | 1 | 9.012182 | Alkaline Metal (s) |
5 | B | Boron | 12 | 10.811 | Metalloid Boron (p) |
ResizeMode.Container
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid T="Element" Items="" ColumnResizeMode="@(_resizeColumn ? ResizeMode.Column : ResizeMode.Container)" RowsPerPage="5"> <Columns> <PropertyColumn Property="x => x.Number" Title="Nr" /> <PropertyColumn Property="x => x.Sign" Resizable="false" /> <PropertyColumn Property="x => x.Name" /> <PropertyColumn Property="x => x.Position" /> <PropertyColumn Property="x => x.Molar" Title="Molar mass" /> <PropertyColumn Property="x => x.Group" Title="Category" /> </Columns> <PagerContent> <MudDataGridPager T="Element" PageSizeOptions=@(new int[] {5, 10, 20}) /> </PagerContent> </MudDataGrid> <div class="d-flex flex-wrap mt-4"> <div class="d-flex justify-start align-center"> <p class="mud-typography mud-typography-body1 mud-inherit-text mr-2">ResizeMode.Container</p> <MudSwitch @bind-Value="_resizeColumn" Color="Color.Primary">ResizeMode.Column</MudSwitch> </div> </div>
@code { private IEnumerable<Element> Elements = new List<Element>(); private bool _resizeColumn; protected override async Task OnInitializedAsync() { Elements = await httpClient.GetFromJsonAsync<List<Element>>("webapi/periodictable"); } }
Data Aggregation
The <MudDataGrid>
allows you to aggregate data in several different ways. Data aggregation happens in the
footer of the grid for the most part. By setting an AggregateDefinition
, you can easily add a quick built-in aggregate
or choose to tailor the display to your needs. There are 6 different AggregateTypes
that can be used with the
AggregateDefinition
: Avg, Count, Custom, Max, Min and Sum. For more control over the data aggregation, you can choose the
AggregationType.Custom
and supply your own function which will return a formatted string to display. Lastly, for
complete control over the data aggregation including the look and feel, you use <FooterTemplate>
which has its
context set to the CurrentPageItems
.
Aggregation is automatically applied to groups when the data grid is grouped by a column. Try it out by grouping the Status column!
Name | Age | Status | Salary | Hired | Manager |
---|---|---|---|---|---|
Sam | 56 | Normal | 50000.00 | 3/5/2005 | False |
Alicia | 54 | Info | 75000.00 | 1/17/2010 | False |
Ira | 27 | Success | 102000.00 | 6/15/2017 | True |
John | 32 | Warning | 132000.00 | 12/23/2021 | True |
Fred | 65 | Warning | 87000.00 | 7/3/2003 | False |
Tabitha | 33 | Info | 157000.00 | 2/12/2015 | True |
Hunter | 22 | Success | 43000.00 | 9/20/2017 | False |
Esme | 55 | Warning | 149000.00 | 8/1/2017 | True |
People:
S am, A licia, I ra, J ohn, F red, T abitha, H unter, E sme | Average age is 43 | Highest: $157,000 | 4 Over $100,000 |
@using System.Net.Http.Json @inject HttpClient httpClient <MudDataGrid Items="@_items" Groupable="true" Filterable="true"> <Columns> <PropertyColumn Property="x => x.Name"> <FooterTemplate> @{ int index = 1, count = @context.Items.Count(); } People: @foreach (var person in @context.Items) { <MudAvatar Color="@((Color)index)" Variant="Variant.Outlined" Size="Size.Small" Class="mr-1">@person.Name.First()</MudAvatar>@person.Name.Substring(1) if (index < count) { @(", ") } index++; } </FooterTemplate> </PropertyColumn> <PropertyColumn Property="x => x.Age" AggregateDefinition="_ageAggregation" /> <PropertyColumn Property="x => x.Status"></PropertyColumn> <PropertyColumn Property="x => x.Salary" AggregateDefinition="_salaryAggregation" /> <PropertyColumn Property="x => x.HireDate" Title="Hired"> <CellTemplate> @context.Item.HireDate.ToString("d") </CellTemplate> </PropertyColumn> <PropertyColumn Property="x => x.IsManager" Title="Manager" /> </Columns> </MudDataGrid>
@code { public record Model (string Name, int Age, Severity Status, decimal Salary, DateTime HireDate, bool IsManager); IEnumerable<Model> _items = new List<Model>() { new Model("Sam", 56, Severity.Normal, 50_000.00M, new DateTime(2005, 3, 5), false), new Model("Alicia", 54, Severity.Info, 75_000.00M, new DateTime(2010, 1, 17), false), new Model("Ira", 27, Severity.Success, 102_000.00M, new DateTime(2017, 6, 15), true), new Model("John", 32, Severity.Warning, 132_000.00M, new DateTime(2021, 12, 23), true), new Model("Fred", 65, Severity.Warning, 87_000.00M, new DateTime(2003, 7, 3), false), new Model("Tabitha", 33, Severity.Info, 157_000.00M, new DateTime(2015, 2, 12), true), new Model("Hunter", 22, Severity.Success, 43_000.00M, new DateTime(2017, 9, 20), false), new Model("Esme", 55, Severity.Warning, 149_000.00M, new DateTime(2017, 8, 1), true) }; AggregateDefinition<Model> _ageAggregation = new AggregateDefinition<Model> { Type = AggregateType.Avg, DisplayFormat = "Average age is {value}" }; AggregateDefinition<Model> _salaryAggregation = new AggregateDefinition<Model> { Type = AggregateType.Custom, CustomAggregate = x => { var highestSalary = x.Max(z => z.Salary); var countOver100Grand = x.Count(z => z.Salary > 100_000); return $"Highest: {highestSalary:C0} | {countOver100Grand} Over {100000:C0}"; } }; }
Sticky Columns
The <MudDataGrid>
allows you to make a column stick to the left or right. Setting the StickyLeft
or StickyRight
properties
to true
will make those columns "sticky". You must turn on HorizontalScrollbar
to see the columns stick to either side.
There are a couple of things to keep in mind with sticky columns. First, if there are not enough columns and data to force the data grid to scroll, you will not see
the columns stick, and that is by design and simply how sticky works in CSS. Secondly, there is nothing stopping you from making multiple columns sticky, but it will
not have the effect you presumably intend. Instead, each column will be sticky when it reached the left or right side of the data grid and will overlap the sticky column
before it.
Name | Age | This is a really long column ... | Salary | |
---|---|---|---|---|
Sam | 56 | ... | 50000.00 | |
Alicia | 54 | ... | 75000.00 | |
Ira | 27 | ... | 102000.00 | |
John | 32 | ... | 132000.00 | |
@using System.Net.Http.Json <MudDataGrid Items="@_users" HorizontalScrollbar="true" Bordered="true" Dense="true"> <Columns> <PropertyColumn Property="x => x.Name" StickyLeft="true" /> <PropertyColumn Property="x => x.Age" /> <PropertyColumn Property="x => x.FillerColumn" HeaderStyle="white-space:nowrap"> <HeaderTemplate> @((MarkupString)$"This is a really long column{string.Join("", Enumerable.Repeat(" ", 1000))}...") </HeaderTemplate> </PropertyColumn> <PropertyColumn Property="x => x.Salary" /> <TemplateColumn StickyRight="true"> <CellTemplate> <MudIconButton Icon="@Icons.Material.Outlined.Edit" Size="@Size.Small" /> </CellTemplate> </TemplateColumn> </Columns> </MudDataGrid>
@code { public record User(string Name, int Age, string FillerColumn, decimal Salary); private IEnumerable<User> _users = new List<User> { new User("Sam", 56, "...", 50_000.00M), new User("Alicia", 54, "...", 75_000.00M), new User("Ira", 27, "...", 102_000.00M), new User("John", 32, "...", 132_000.00M), }; }
Server Side Filtering, Sorting and Pagination
Set ServerData
to load data from the backend that is filtered, sorted and paginated.
DataGrid will call this async function whenever the user navigates the pager or changes sorting by clicking on the sort header icons.
In this example, we also show how to force the datagrid to update when the search textfield blurs, so that the datagrid reloads server-filtered data.
Nr | Sign | Name | Position | Molar mass | Category |
---|---|---|---|---|---|
@using System.Net.Http.Json @using System.Threading @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid @ref="dataGrid" T="Element" ServerData="ServerReload" Filterable="false"> <ToolBarContent> <MudText Typo="Typo.h6">Periodic Elements</MudText> <MudSpacer /> <MudTextField T="string" ValueChanged="@(s=>OnSearch(s))" Placeholder="Search" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"></MudTextField> </ToolBarContent> <Columns> <PropertyColumn Property="x => x.Number" Title="Nr" /> <PropertyColumn Property="x => x.Sign" /> <PropertyColumn Property="x => x.Name" /> <PropertyColumn Property="x => x.Position" /> <PropertyColumn Property="x => x.Molar" Title="Molar mass" /> <PropertyColumn Property="x => x.Group" Title="Category" /> </Columns> <PagerContent> <MudDataGridPager T="Element" /> </PagerContent> </MudDataGrid>
@code { MudDataGrid<Element> dataGrid; string searchString = null; /// <summary> /// Here we simulate getting the paged, filtered and ordered data from the server /// </summary> private async Task<GridData<Element>> ServerReload(GridState<Element> state) { IEnumerable<Element> data = await httpClient.GetFromJsonAsync<List<Element>>("webapi/periodictable"); await Task.Delay(300); data = data.Where(element => { if(string.IsNullOrWhiteSpace(searchString)) return true; if(element.Sign.Contains(searchString, StringComparison.OrdinalIgnoreCase)) return true; if(element.Name.Contains(searchString, StringComparison.OrdinalIgnoreCase)) return true; if($"{element.Number} {element.Position} {element.Molar}".Contains(searchString)) return true; return false; }).ToArray(); var totalItems = data.Count(); var sortDefinition = state.SortDefinitions.FirstOrDefault(); if(sortDefinition != null) { switch(sortDefinition.SortBy) { case nameof(Element.Number): data = data.OrderByDirection( sortDefinition.Descending ? SortDirection.Descending : SortDirection.Ascending, o => o.Number ); break; case nameof(Element.Sign): data = data.OrderByDirection( sortDefinition.Descending ? SortDirection.Descending : SortDirection.Ascending, o => o.Sign ); break; case nameof(Element.Name): data = data.OrderByDirection( sortDefinition.Descending ? SortDirection.Descending : SortDirection.Ascending, o => o.Name ); break; case nameof(Element.Position): data = data.OrderByDirection( sortDefinition.Descending ? SortDirection.Descending : SortDirection.Ascending, o => o.Position ); break; case nameof(Element.Molar): data = data.OrderByDirection( sortDefinition.Descending ? SortDirection.Descending : SortDirection.Ascending, o => o.Molar ); break; } } var pagedData = data.Skip(state.Page * state.PageSize).Take(state.PageSize).ToArray(); return new GridData<Element> { TotalItems = totalItems, Items = pagedData }; } private Task OnSearch(string text) { searchString = text; return dataGrid.ReloadServerData(); } }
Virtualization
The items in the <MudDataGrid>
can be virtualized to provide better rendering performance. Setting the Virtualize
property
to true
will cause the items to be rendered virtually. You must restrict the height for virtualization to work.
Column1 | Column2 | Column3 | Column4 | Column5 |
---|---|---|---|---|
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models <MudDataGrid Items="@_items" Virtualize="true" FixedHeader="true" Height="350px"> <Columns> <PropertyColumn Property="x => x.Column1" /> <PropertyColumn Property="x => x.Column2" /> <PropertyColumn Property="x => x.Column3" /> <PropertyColumn Property="x => x.Column4" /> <PropertyColumn Property="x => x.Column5" /> </Columns> </MudDataGrid>
@code { public record Model(string Column1, string Column2, string Column3, string Column4, string Column5); private List<Model> _items = new List<Model>(); protected override void OnInitialized() { for (var i = 0; i < 20000; i++) _items.Add(new Model($"Value_{i}", $"Value_{i}", $"Value_{i}", $"Value_{i}", $"Value_{i}")); } }
Virtualize server data
The <MudDataGrid>
supports virtualization of data fetched from a server, enhancing the grid's performance for large datasets.
For this feature to work, the Virtualize
property must be set to true
,
the VirtualizeServerData
parameter should be used to facilitate data retrieval and streaming from the server,
and the ItemSize
should be specified to optimize virtualization.
Please make sure to constrain the grid's height, as virtualization relies on this dimension.
Number |
---|
@using System.Threading <MudDataGrid T="int" VirtualizeServerData="ServerDataFunc" Virtualize="true" Filterable FixedHeader Height="400px" ItemSize="52.68f"> <Columns> <PropertyColumn Property="x => x" Title="Number" /> </Columns> <RowLoadingContent> <tr class="mud-table-row"> <td class="mud-table-cell" colspan="1000"> Loading... </td> </tr> </RowLoadingContent> </MudDataGrid>
@code { private readonly List<int> _items = Enumerable.Range(0, 51).ToList(); private async Task<GridData<int>> ServerDataFunc(GridStateVirtualize<int> gridState, CancellationToken token) { try { var result = _items.ToList(); await Task.Delay(1000, token); if (gridState.SortDefinitions.Count > 0) { var firstSort = gridState.SortDefinitions.First(); result = firstSort.Descending ? result.OrderByDescending(firstSort.SortFunc).ToList() : result.OrderBy(firstSort.SortFunc).ToList(); } if (gridState.FilterDefinitions.Any()) { var filterFunctions = gridState.FilterDefinitions.Select(x => x.GenerateFilterFunction()); result = result .Where(x => filterFunctions.All(f => f(x))) .ToList(); } var totalNumberOfFilteredItems = result.Count; result = result .Skip(gridState.StartIndex) .Take(gridState.Count) .ToList(); return new GridData<int> { Items = result, TotalItems = totalNumberOfFilteredItems }; } catch (TaskCanceledException) { return new GridData<int> { Items = [], TotalItems = 0 }; } } }
Observability
When loading the <MudDataGrid>
with a collection that implements INotifyCollectionChanged
, changes to the
underlying collection will automatically be reflected in the <MudDataGrid>
.
Name | Age | Status | Salary | Hired | Manager |
---|---|---|---|---|---|
Sam | 56 | Normal | 50000.00 | 3/5/2005 12:00:00 AM | False |
Alicia | 54 | Info | 75000.00 | 1/17/2010 12:00:00 AM | False |
Ira | 27 | Success | 102000.00 | 6/15/2017 12:00:00 AM | True |
John | 32 | Warning | 132000.00 | 12/23/2021 12:00:00 AM | True |
Fred | 65 | Warning | 87000.00 | 7/3/2003 12:00:00 AM | False |
Tabitha | 33 | Info | 157000.00 | 2/12/2015 12:00:00 AM | True |
Hunter | 22 | Success | 43000.00 | 9/20/2017 12:00:00 AM | False |
Esme | 55 | Warning | 149000.00 | 8/1/2017 12:00:00 AM | True |
@using System.Net.Http.Json @using System.Collections.ObjectModel @inject HttpClient httpClient <MudButton OnClick="" Color="@Color.Success" Class="add-item-btn">Add Item</MudButton> <MudButton OnClick="" Color="@Color.Error" Class="remove-item-btn">Remove Item</MudButton> <MudDataGrid Items="@_items"> <Columns> <PropertyColumn Property="x => x.Name" /> <PropertyColumn Property="x => x.Age" /> <PropertyColumn Property="x => x.Status" /> <PropertyColumn Property="x => x.Salary" /> <PropertyColumn Property="x => x.HireDate" Title="Hired" /> <PropertyColumn Property="x => x.IsManager" Title="Manager" /> </Columns> </MudDataGrid>
@code { public record Model (string Name, int Age, Severity Status, decimal Salary, DateTime HireDate, bool IsManager); ObservableCollection<Model> _items = new ObservableCollection<Model>() { new Model("Sam", 56, Severity.Normal, 50_000.00M, new DateTime(2005, 3, 5), false), new Model("Alicia", 54, Severity.Info, 75_000.00M, new DateTime(2010, 1, 17), false), new Model("Ira", 27, Severity.Success, 102_000.00M, new DateTime(2017, 6, 15), true), new Model("John", 32, Severity.Warning, 132_000.00M, new DateTime(2021, 12, 23), true), new Model("Fred", 65, Severity.Warning, 87_000.00M, new DateTime(2003, 7, 3), false), new Model("Tabitha", 33, Severity.Info, 157_000.00M, new DateTime(2015, 2, 12), true), new Model("Hunter", 22, Severity.Success, 43_000.00M, new DateTime(2017, 9, 20), false), new Model("Esme", 55, Severity.Warning, 149_000.00M, new DateTime(2017, 8, 1), true) }; void AddItem() { _items.Add(new Model("New Person", 44, Severity.Warning, 85_000.00M, new DateTime(2022, 1, 1), true)); } void RemoveItem() { if (_items.Any()) { _items.RemoveAt(0); } } }
CultureInfo
DataGrid Culture
(CultureInfo) property is used to display and editing/filter columns data.
Each <Column>
can define his own culture,
to allow to specify its format individually.
Name | Age | Amount (es-ES culture) | Total (invariant culture) |
---|---|---|---|
Sam | 56 | 2,3 | 3.2 |
Alicia | 54 | 4,5 | 4.9 |
Ira | 27 | 2,1 | 2.5 |
John | 32 | 5,9 | 6.1 |
@using System.Globalization <MudDataGrid Items="@_items" Filterable="true"> <Columns> <PropertyColumn Property="x => x.Name" /> <PropertyColumn Property="x => x.Age" /> <PropertyColumn Property="x => x.Amount" Title="Amount (es-ES culture)" Culture="@(new CultureInfo("es-ES"))" /> <PropertyColumn Property="x => x.Total" Title="Total (invariant culture)" Culture="@CultureInfo.InvariantCulture" /> </Columns> </MudDataGrid>
@code { private IEnumerable<Model> _items = new List<Model>() { new Model("Sam", 56, 2.3, 3.2), new Model("Alicia", 54, 4.5, 4.9), new Model("Ira", 27, 2.1, 2.5), new Model("John", 32, 5.9, 6.1) }; public record Model(string Name, int? Age, double? Amount, double? Total); }
Column Reordering
To enable Column Reordering via Drag and Drop, set the DragDropColumnReordering
parameter to true. Columns can override this parameter with their DragAndDropEnabled
parameter if necessary.
In the example all but two fixed columns can be reordered by dragging their header onto another column header to swap places. On mouse-over the draggable columns show their DragIndicatorIcon
and when dragging
a header over another column header, it will signal its ability to swap places by changing its text color. The drag-over effect can be customized by setting parameters DropAllowedClass
and DropNotAllowedClass
to your own CSS classes.
Nr (fixed) |
Sign |
Name (fixed) |
Position |
Molar mass |
Category | |
---|---|---|---|---|---|---|
1 | H | Hydrogen | 0 | 1.00794 | Other | |
2 | He | Helium | 17 | 4.002602 | Noble Gas (p) | |
3 | Li | Lithium | 0 | 6.941 | Alkaline Earth Metal (s) | |
4 | Be | Beryllium | 1 | 9.012182 | Alkaline Metal (s) | |
5 | B | Boron | 12 | 10.811 | Metalloid Boron (p) | |
6 | C | Carbon | 13 | 12.0107 | Nonmetal Carbon (p) | |
7 | N | Nitrogen | 14 | 14.0067 | Nonmetal Pnictogen (p) | |
8 | O | Oxygen | 15 | 15.9994 | Nonmetal Chalcogen (p) | |
9 | F | Fluorine | 16 | 18.998404 | Halogen (p) | |
10 | Ne | Neon | 17 | 20.1797 | Noble Gas (p) | |
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid T="Element" Items="@_elements" DragDropColumnReordering="@_reorderingEnabled" ApplyDropClassesOnDragStarted="@_applyDropClassesOnDragStarted" DragIndicatorIcon="@_dragIndicatorIcon" Dense ColumnResizeMode="ResizeMode.Container"> <Columns> <SelectColumn T="Element"/> <PropertyColumn Property="x => x.Number" Title="Nr (fixed)" DragAndDropEnabled="false"/> <PropertyColumn Property="x => x.Sign"/> <PropertyColumn Property="x => x.Name" Title="Name (fixed)" DragAndDropEnabled="false" /> <PropertyColumn Property="x => x.Position" /> <PropertyColumn Property="x => x.Molar" Title="Molar mass" /> <PropertyColumn Property="x => x.Group" Title="Category" /> </Columns> <PagerContent> <MudDataGridPager T="Element" /> </PagerContent> </MudDataGrid> <div class="d-flex flex-column mt-4"> <MudSwitch @bind-Value="_reorderingEnabled" Color="Color.Primary">DragDropColumnReordering</MudSwitch> <MudSwitch @bind-Value="_applyDropClassesOnDragStarted" Color="Color.Primary">ApplyDropClassesOnDragStarted</MudSwitch> </div>
@code { IEnumerable<Element> _elements = new List<Element>(); bool _applyDropClassesOnDragStarted = false; string _dragIndicatorIcon = Icons.Material.Filled.DragIndicator; bool _reorderingEnabled = true; protected override async Task OnInitializedAsync() { _elements = await httpClient.GetFromJsonAsync<List<Element>>("webapi/periodictable"); } }
Columns Panel
The <MudDataGrid>
can open a columns panel using ShowColumnsPanel
.
The panel allows the re-ordering, hiding, filtering and grouping of columns. The enabled functionality matches the grid and column options except column re-ordering.
Column re-ordering is enabled in the panel using the ColumnsPanelReordering
property. Re-ordering is on an insert basis, so it does not respect the column level DragAndDropEnabled
property which swaps columns.
Nr |
Name |
Position |
Molar mass |
Category |
Template | |
---|---|---|---|---|---|---|
1 | Hydrogen | 0 | 1.00794 | Other | ||
2 | Helium | 17 | 4.002602 | Noble Gas (p) | ||
3 | Lithium | 0 | 6.941 | Alkaline Earth Metal (s) | ||
4 | Beryllium | 1 | 9.012182 | Alkaline Metal (s) | ||
5 | Boron | 12 | 10.811 | Metalloid Boron (p) | ||
6 | Carbon | 13 | 12.0107 | Nonmetal Carbon (p) | ||
7 | Nitrogen | 14 | 14.0067 | Nonmetal Pnictogen (p) | ||
8 | Oxygen | 15 | 15.9994 | Nonmetal Chalcogen (p) | ||
9 | Fluorine | 16 | 18.998404 | Halogen (p) | ||
10 | Neon | 17 | 20.1797 | Noble Gas (p) | ||
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid T="Element" @ref="grid" Items="_elements" DragDropColumnReordering="_dragDropReorderingEnabled" ColumnsPanelReordering="_columnsPanelReorderingEnabled" ColumnResizeMode="ResizeMode.Container" Hideable="_hideable" Filterable="_filterable" Groupable="_groupable" FilterMode="_filterMode" ShowMenuIcon="true"> <Columns> <SelectColumn T="Element"/> <PropertyColumn Property="x => x.Number" Title="Nr" /> <PropertyColumn Property="x => x.Sign" Hidden="true" DragAndDropEnabled="false" Groupable="false" Sortable="false" Filterable="false" /> <PropertyColumn Property="x => x.Name" Title="Name" Hidden="false" DragAndDropEnabled="true" Groupable="true" Sortable="true" Filterable="true" Grouping="false" /> <PropertyColumn Property="x => x.Position" Filterable="false" Hideable="false" /> <PropertyColumn Property="x => x.Molar" Title="Molar mass" @bind-Hidden="_hideMolar" @bind-Grouping="_groupMolar" Hideable="true" /> <PropertyColumn Property="x => x.Group" Hidden="_hideCategory" Grouping="_groupCategory" Title="Category" /> <TemplateColumn Title="Template" /> </Columns> <PagerContent> <MudDataGridPager T="Element" /> </PagerContent> </MudDataGrid> <div class="d-flex flex-rows flex-wrap mr-4"> <MudSwitch @bind-Value="_dragDropReorderingEnabled" Color="Color.Primary">Drag Drop Column Reordering</MudSwitch> <MudSwitch @bind-Value="_columnsPanelReorderingEnabled" Color="Color.Primary">Columns Panel Column Reordering</MudSwitch> <MudSwitch @bind-Value="_filterable" Color="Color.Primary">Filterable</MudSwitch> </div> <div class="d-flex flex-rows flex-wrap mr-4"> <MudSwitch @bind-Value="_hideable" Color="Color.Primary">Hideable</MudSwitch> <MudSwitch @bind-Value="_hideMolar" Color="Color.Primary" Converter="_oppositeBoolConverter">Molar Mass Visible</MudSwitch> <MudSwitch @bind-Value="_hideCategory" Color="Color.Primary" Converter="_oppositeBoolConverter">Category Visible</MudSwitch> </div> <div class="d-flex flex-wrap mt-4 gap-1"> <MudButton OnClick="@(() => HideColumnsAsync(false))" Variant="Variant.Filled" Color="Color.Primary">Show All Columns</MudButton> <MudButton OnClick="@(() => HideColumnsAsync(true))" Variant="Variant.Filled" Color="Color.Primary">Hide All Columns</MudButton> </div> <div class="d-flex flex-rows flex-wrap mr-4"> <MudSwitch @bind-Value="_groupable" Color="Color.Primary">Groupable</MudSwitch> <MudSwitch @bind-Value="_groupMolar" Color="Color.Primary">Group By Molar</MudSwitch> <MudSwitch @bind-Value="_groupCategory" Color="Color.Primary">Group By Category</MudSwitch> </div> <div class="d-flex flex-wrap mt-4"> <MudRadioGroup T="DataGridFilterMode" @bind-Value="_filterMode"> <MudRadio Dense="true" Value="@DataGridFilterMode.Simple" Color="Color.Primary">Simple</MudRadio> <MudRadio Dense="true" Value="@DataGridFilterMode.ColumnFilterMenu" Color="Color.Tertiary">Column Menu</MudRadio> <MudRadio Dense="true" Value="@DataGridFilterMode.ColumnFilterRow">Column Row</MudRadio> </MudRadioGroup> </div>
@code { private IEnumerable<Element> _elements = new List<Element>(); private DataGridFilterMode _filterMode = DataGridFilterMode.Simple; private bool _dragDropReorderingEnabled = true; private bool _columnsPanelReorderingEnabled = true; private bool _hideable = true; private bool _filterable = true; private bool _groupable = true; private bool _hideMolar = false; private bool _hideCategory = false; private bool _groupMolar = false; private bool _groupCategory = false; public MudDataGrid<Element> grid = null; private MudBlazor.Converter<bool, bool?> _oppositeBoolConverter = new() { SetFunc = value => !value, GetFunc = value => !value ?? true, }; protected override async Task OnInitializedAsync() { _elements = await httpClient.GetFromJsonAsync<List<Element>>("webapi/periodictable"); } private async Task HideColumnsAsync(bool hide) { foreach (var column in grid.RenderedColumns) { if (hide) { await column.HideAsync(); } else { await column.ShowAsync(); } }; } }
Validator
When a <MudDataGrid>
is used as part of a MudForm
you might want to
bind the Validator
property to the outer MudForm
so that validation
and IsTouched
states are reflected in/propagated to the outer MudForm
.
<MudForm @ref="_form" ValidationDelay="0"> <MudDataGrid T="Item" Items="_items" Validator="@(_bindValidatorToForm ? _form : _defaultValidator)"> <Columns> <TemplateColumn Title="Name"> <CellTemplate> <MudTextField @bind-Value="context.Item.Name" Immediate="true" Validation="(string name) => ValidateName(name)" /> </CellTemplate> </TemplateColumn> </Columns> </MudDataGrid> </MudForm> <MudStack Row> <MudSwitch Color="Color.Primary" @bind-Value="_bindValidatorToForm">Bind MudDataGrid.Validator to MudForm?</MudSwitch> <MudSwitch ReadOnly="true" Value="_form?.IsTouched">MudForm.IsTouched</MudSwitch> <MudSwitch ReadOnly="true" Value="_form?.IsValid">MudForm.IsValid</MudSwitch> </MudStack>
@code { private readonly Interfaces.IForm _defaultValidator = new DataGridRowValidator(); private MudForm _form; private bool _bindValidatorToForm = true; private Item[] _items = [ new() { Name = "valid" }, new() { Name = "invalid" } ]; private static string ValidateName(string name) { if (string.IsNullOrWhiteSpace(name)) { return "Name is required"; } if (name == "invalid") { return "Name must not be 'invalid'"; } return null; } protected override async Task OnAfterRenderAsync(bool firstRender) { await base.OnParametersSetAsync(); if (firstRender) { await _form.Validate(); _form.ResetTouched(); } } public class Item { public string Name { get; set; } } }