DataGrid

A sortable, filterable data grid with multiselection and pagination.

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 it's simplest form, the data grid is just a table, displaying data from a data source. In it's 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 an 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="@employees" 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.

Periodic Elements
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)

Rows per page:

10

1-10 of 88

Show Events
@using System.Net.Http.Json
@using MudBlazor.Examples.Data.Models
@inject HttpClient httpClient

<MudDataGrid T="Element" MultiSelection="true" Items="@Elements" SortMode="SortMode.Multiple" Filterable="true" QuickFilter="@_quickFilter"
    Hideable="true" RowClick="@RowClicked" RowContextMenuClick="RowRightClicked" SelectedItemsChanged="@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

Show Events
@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="@StartedEditingItem" CanceledEditingItem="@CanceledEditingItem" CommittedItemChanges="@CommittedItemChanges"
    Bordered="true" Dense="true" EditTrigger="@(_editTriggerRowClick ? DataGridEditTrigger.OnRowClick : DataGridEditTrigger.Manual)">
    <Columns>
        <PropertyColumn Property="x => x.Number" Title="Nr" IsEditable="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">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">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)}");
    }
}

Copyright © 2020-2026 MudBlazor.

Powered by .NET 8.0.27

An error has occurred. This application may no longer respond until reloaded. Reload 🗙