Skip to main content Skip to footer

Upgrading the Blazor HTML Table With FlexGrid

Blazor is a web development platform that allows you to create applications entirely in C# and HTML without the hassle of writing JavaScript. The Blazor user interface is defined in razor files that mix HTML with C#. To display tabular data your only option is to use a basic HTML table. You can do this by just writing the table markup in the razor file as you would in a normal HTML file.

But if you need to add more interaction, like editing, selection, sorting, filtering, and grouping, you'll need to use a fully developed Blazor component. This is where FlexGrid for Blazor can help. FlexGrid is a native, full-featured data grid component that delivers all the interaction you need with little effort, and it has full compatibility with all the major browsers.

In this article, I will guide you through replacing the HTML “Weather Forecast” table in the default Blazor template with FlexGrid. I will also show you some different features of the grid including the different data virtualization techniques you could use in your app to efficiently display large data sets.

Creating a New Blazor Project

Open Visual Studio 2019 and create a new “Blazor App” project.

Upgrading the Blazor HTML Table with FlexGrid

Give the new project a name.

Upgrading the Blazor HTML Table with FlexGrid

In this walkthrough, I'll create a Server App. This means the app will include an ASP. NET Core server-side portion. Blazor Server was released along with .NET Core 3.0 earlier this year, whereas the WebAssembly version of Blazor, that runs completely on the client, is not officially released yet.

Upgrading the Blazor HTML Table with FlexGrid

The created project will come with a predefined set of pages including some basic UI to display the weather forecast in a table. Open up the FetchData.razor file.

Upgrading the Blazor HTML Table with FlexGrid

The FetchData.razor sample displays “Loading...” text until the data is available. Then, it renders an HTML table with the headers and rows. This table is what we will replace to use FlexGrid for Blazor instead.

Upgrading the Blazor HTML Table with FlexGrid

You can first build and run the app to see the weather forecast table.

Upgrading the Blazor HTML Table with FlexGrid

Replacing the HTML Table with FlexGrid

The HTML table is pretty much the only way to display tabular data in Blazor without using any 3rd party library. But the table lacks functionality so we will need to update it to use a data grid control such as FlexGrid.

To add FlexGrid, first we need to add the nuget package “C1.Blazor.Grid” that it is publicly available in nuget.org. Right-click the project file and select Manage Nuget Packages. From there, you can browse to find the C1.Blazor.Grid library, and install it to the project.

Upgrading the Blazor HTML Table with FlexGrid

The C1.Blazor.Grid library has several dependencies which will be checked and installed if they are not already.

Upgrading the Blazor HTML Table with FlexGrid

You can see the package after it’s installed under the Dependencies folder of your project.

Upgrading the Blazor HTML Table with FlexGrid

Next, we need to add a series of links and scripts in the file _Host.cshtml that is in the folder “Pages”.

<link rel="stylesheet" href="~/_content/C1.Blazor.Core/styles.css" />
<link rel="stylesheet" href="~/_content/C1.Blazor.Grid/styles.css" /> 
<link rel="stylesheet" href="~/_content/C1.Blazor.ListView/styles.css" /> 
<link rel="stylesheet" href="~/_content/C1.Blazor.Input/styles.css" /> 
<link rel="stylesheet" href="~/_content/C1.Blazor.DataPager/styles.css" /> 
<script src="~/_content/C1.Blazor.Core/scripts.js"></script>
<script src="~/_content/C1.Blazor.Input/scripts.js"></script> 
<script src="~/_content/C1.Blazor.Grid/scripts.js"></script> 

Back in the FetchData.razor file, we will add the following using declaration

@using C1.Blazor.Grid

Now we need to replace the HTML table markup with the following markup to obtain a similar interface to the original sample.

<FlexGrid ItemsSource="forecasts" AutoGenerateColumns="false" DefaultColumnWidth="GridLength.Star" ColumnHeaderStyle="@("font-weight:bold")">  
    <FlexGridColumns>  
        <GridColumn Binding="Date" Format="d"/>  
        <GridColumn Binding="TemperatureC" Header="Temp. (C)" />  
        <GridColumn Binding="TemperatureF" Header="Temp. (F)" />  
        <GridColumn Binding="Summary" />  
    </FlexGridColumns>  
</FlexGrid>

When you build and run the project, you should see FlexGrid displaying the weather forecast.

Upgrading the Blazor HTML Table with FlexGrid

At this point, the sample looks the same as the original sample, but we gained new features, like selection, keyboard navigation, and editing capabilities.

Upgrading the Blazor HTML Table with FlexGrid

We also now have the ability to sort by clicking the column headers
Upgrading the Blazor HTML Table with FlexGrid

Adding Filtering to the Blazor Grid

Next, we'll demonstrate how to add filtering capabilites to our Blazor data grid, FlexGrid, by just adding a few more lines of code.

To support filtering we will add a textbox above the grid and “hook it up” to the FlexGrid to provide the filter string. The typed text will filter the rows of the grid. We could use a basic HTML input element, but since we already have the C1.Blazor libraries referenced in our app (since they were dependencies to FlexGrid) let’s use the C1TextBox control.

The NuGet package for C1TextBox (it’s included in C1.Blazor.Input) is already added to the project. Now just add a using statement of the “Input” library to be able to use C1TextBox.

 @using C1.Blazor.Input
<C1TextBox @bind-Text="filterText" />

Next, we'll add the FullTextFilterBehavior to FlexGrid. This behavior basically encapsulates all of the logic that we would need to “hook up” the text box and the data grid (such as listening to the text changed event and applying the filter to the FlexGrid data, and so on). The feature truly is built-in!

<FlexGridBehaviors> 

    <FullTextFilterBehavior FilterString="@filterText" MatchNumbers="true" /> 

</FlexGridBehaviors>

The C1TextBox changes the “filterText” field and the full-text filter behavior handles filtering the data of the grid, as well as highlighting the matches.

Upgrading the Blazor HTML Table with FlexGrid

Adding Grouping to the Blazor Grid

Another popular feature of data-grids is grouping. To group the data in FlexGrid, we will assign a C1CollectionView as the ItemsSource of the grid, instead of the raw data. This way we can call GroupAsync in the initialization method of the page and FlexGrid will do the rest.

protected override async Task OnInitializedAsync()  
{  
    var data = await ForecastService.GetForecastAsync(DateTime.Now);  
    var collection = new C1CollectionView<WeatherForecast>(data);  
    await collection.GroupAsync(nameof(WeatherForecast.Summary));  
    forecasts = collection;  
}

Upgrading the Blazor HTML Table with FlexGrid

To display an icon instead of text in the column “Summary”, we will use the CellTemplate property of the column and map every possible value to a corresponding HTML “img” with its respective icon.

<GridColumn Binding="Summary">  
    <CellTemplate>  
        @switch (context)  
        {  
            case "Freezing":  
                <img style="width:20px;height:20px" src="freezing.png" />  
                break;  
            case "Bracing":  
                <img style="width:20px;height:20px" src="bracing.png" />  
                break;  
            case "Chilly":  
                <img style="width:20px;height:20px" src="chilly.png" />  
                break;  
            case "Cool":  
                <img style="width:20px;height:20px" src="cool.png" />  
                break;  
            case "Mild":  
                <img style="width:20px;height:20px" src="mild.png" />  
                break;  
            case "Warm":  
                <img style="width:20px;height:20px" src="warm.png" />  
                break;  
            case "Balmy":  
                <img style="width:20px;height:20px" src="balmy.png" />  
                break;  
            case "Hot":  
                <img style="width:20px;height:20px" src="hot.png" />  
                break;  
            case "Sweltering":  
                <img style="width:20px;height:20px" src="sweltering.png" />  
                break;  
            case "Scorching":  
                <img style="width:20px;height:20px" src="scorching.png" />  
                break;  
        }  
    </CellTemplate>  
</GridColumn>

Upgrading the Blazor HTML Table with FlexGrid

Adding Data Virtualization for Large Data Sets

FlexGrid offers a rich variety of data-virtualization implementations through C1CollectionView.

The oldest and very popular data-virtualization technique is client-side pagination. It consists of a series of buttons representing the different pages where users can navigate by clicking the buttons.

Adding Paging

Let’s enable paging. To do so, first add a reference to “C1.Blazor.DataPager.”

Upgrading the Blazor HTML Table with FlexGrid

Then, in the FetchData.razor file, add the C1DataPager @using statement at the beginning, and the following markup below the grid.

@using C1.Blazor.DataPager  
<C1DataPager Source="forecasts" />

In the code section we will use C1PagedCollectionView and will assign it to both C1DataPager and FlexGrid.

@using C1.CollectionView  
C1PagedCollectionView<WeatherForecast> forecasts;  
protected override async Task OnInitializedAsync()  
{  
    var data = await ForecastService.GetForecastAsync(DateTime.Now);  
    forecasts = new C1PagedCollectionView<WeatherForecast>(data) { PageSize = 5 };  
}

Upgrading the Blazor HTML Table with FlexGrid

Adding Virtual Scrolling

Next, we will use another virtualization technique known as server-side paging, which is offered through C1VirtualCollectionView.

This technique displays the full range of rows in the grid. You can drag the scrollbar and go to the very last row, no matter how many items the collection has. It will request the items in pages as the grid is scrolled. When scrolling, the rows will appear initially empty and will be filled when the real data comes from the server.

Before we enable it, we need to set a height to the grid to avoid it growing too much.

Style="@("height:300px")"

The initialization code just assigns the virtual collection and the collection implementation fetches the data from the service when it is requested.

protected override void OnInitialized()  
{  
    forecasts = new MyVirtualCollectionView() { PageSize = 5 };  
}

public class MyVirtualCollectionView : C1VirtualCollectionView<WeatherForecast>  
{  
    protected override async Task<Tuple<int, IReadOnlyList<WeatherForecast>>> GetPageAsync(int pageIndex, int startingIndex, int count, IReadOnlyList<SortDescription> sortDescriptions = null, FilterExpression filterExpression = null, CancellationToken cancellationToken = default)  
    {  
        var service = new WeatherForecastService();  
        var data = await service.GetForecastAsync(DateTime.Now.AddDays(startingIndex), PageSize);  
        return new Tuple<int, IReadOnlyList<WeatherForecast>>(1_000, data);  
    }  
}

Upgrading the Blazor HTML Table with FlexGrid

Similarly, “Cursor” pagination is designed to work in the server. A page of data is returned together with a token that will be used in a subsequent request to fetch the next page.

“Cursor” pagination doesn’t allow navigating to a specific page, as all the pages need to be pulled sequentially. Despite this drawback,this kind of pagination doesn’t require computing the total number of items which is faster and simplifies the server implementation.

When FlexGrid is used with a C1CursorCollectionView, it will display a spinner at the bottom indicating more pages are being pulled.

protected override void OnInitialized()  
{  
    forecasts = new MyCursorCollectionView();  
}

public class MyCursorCollectionView : C1CursorCollectionView<WeatherForecast>  
{  
    protected override async Task<Tuple<string, IReadOnlyList<WeatherForecast>>> GetPageAsync(int startingIndex, string pageToken, int? count = null, IReadOnlyList<SortDescription> sortDescriptions = null, FilterExpression filterExpression = null, CancellationToken cancellationToken = default)  
    {  
        var service = new WeatherForecastService();  
        var data = await service.GetForecastAsync(DateTime.Now.AddDays(startingIndex));  
        return new Tuple<string, IReadOnlyList<WeatherForecast>>("", data);  
    }  
}

Upgrading the Blazor HTML Table with FlexGrid

In this walkthrough, I showed how easy it is to replace the standard HTML table with a fully-featured data grid component, FlexGrid. While FlexGrid can be installed through NuGet, you should also install the packages from GrapeCity’s main site so that you can get the samples too. The FlexGrid samples give a more details on how to enable the features that I briefly mentioned above.

Alvaro Rivoir

Computer Engineer
comments powered by Disqus