Skip to main content Skip to footer

How to Build a Blazor Datagrid in Your MAUI Application

In the world of app development, developers are constantly striving to find ways to create apps that function on multiple platforms without the need to write separate code for each platform. Recently, Microsoft has presented a new solution to this problem by introducing the MAUI (Multi-platform App UI) framework, which enables developers to create native apps for iOS, Android, Windows, and macOS using just one codebase.

Blazor MAUI is a fresh framework that facilitates building cross-platform mobile and desktop applications using C# and .NET web technologies. With Blazor MAUI, developers can create apps that function natively on iOS, Android, macOS, and Windows by using a common codebase and a programming model with which they are already familiar.

One of the major advantages of Blazor MAUI is that you can incorporate it with ComponentOne controls from GrapeCity. These controls offer a wide range of data visualization, editing, and manipulation features and are extensively used in enterprise applications.

This blog post will look into how to use the ComponentOne FlexGrid control with Blazor MAUI. We will go over the basics of getting started with Blazor MAUI, as well as some advanced techniques for customizing and extending the controls to cater to specific requirements.

Prerequisite:

  • Visual Studio with the .NET Multi-platform App UI development workload
  • Microsoft Edge WebView2: WebView2 is required on Windows when running a native app. When developing .NET MAUI Blazor apps and only running them in Visual Studio's emulators, WebView2 isn't required

Ready to Start Building? Download ComponentOne Today!

There will be two major steps for this blog:

  1. Create a .NET MAUI Blazor App
  2. Integrate FlexGrid for Blazor

Create a .NET MAUI Blazor App

Launch Visual Studio. In the Start Window, select Create a new project:

Create a New Project - Blazor MAUI Datagrid

In the Create a new project window, use the Project type dropdown to filter MAUI templates:

Project Type MAUI- Blazor Datagrid MAUI

Select the .NET MAUI Blazor App template and then select the Next button:

.NET MAUI Blazor App

In the Configure your new project dialog:

  • Set the Project name to MauiBlazor.
  • Choose a suitable location for the project.
  • Select the Next button.

.NET MAUI Blazor App

Select the framework version with the Framework dropdown list in the Additional information dialog. Select the Create button:

Create .NET MAUI Blazor App

Wait for dependencies to be restored - they should look like the image below:

.NET MAUI Blazor App Dependencies

In the Visual Studio toolbar, select the Windows Machine button to build and start the project:

Visual Studio Window Machine Button

If Developer Mode isn't enabled, you're prompted to enable it in Settings > For developers > Developer Mode (Windows 10) or Settings > Privacy & security > For developers > Developer Mode (Windows 11). Set the switch to On.

Here is the app running as a Windows desktop app:

MAUI Datagrid App

Integrate Flexgrid for Blazor

Go to the Project tab and click on manage NuGet Packages. You will see a screen like the one below.

NuGet Packages Blazor MAUI Datagrid

Click on the Browse tab and search for C1.Blazor.Grid and install the first result that appears.

Blazor Datagrid

Go to the Pages⇒FetchData.razor file and comment on the tables that are used. We will replace this by the Blazor FlexGrid control.

Blazor Datagrid Control

Import the C1.Blazor.Grid at the top.

Blazor MAUI Datagrid

Define the FlexGrid component in the razor page and bind the datasource (ItemsSource) to the forecasts collection from the weather forecast service that was already set up in the project template.

Datagrid Component

Add the CSS file links to wwwroot/index.html:

<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.Input/styles.css" />

Add JS file scripts to wwwroot/index.html:

<script src="/_content/C1.Blazor.Core/scripts.js"></script>
<script src="/_content/C1.Blazor.Grid/scripts.js"></script>
<script src="/_content/C1.Blazor.Input/scripts.js"></script>

Datagrid Blazor MAUI

Congratulations! Now you have added the FlexGrid for Blazor to the MAUI app successfully. Run the app in the windows emulator.

The fetched data will display just like in the grid below:

MAUI Datagrid App

Add More Controls to the MAUI App

Next, let's filter the data of the grid by adding some other controls included with ComponentOne Blazor Edition. We will add an AutoComplete feature that allows users to select a customer from a list of options by typing in the customer's name. Once the user selects a customer and presses enter, the FlexGrid layout displays rows of data related to that particular customer only.

In other words, the AutoComplete feature helps users easily find and select a customer they want to view data for. The FlexGrid layout efficiently organizes and displays the data for the selected customer. Together, these features provide a seamless user experience for browsing and viewing data related to specific customers.

Add the following code in the fetchData.razor file:

@page "/fetchdata"
@using C1.Blazor.Core
@using C1.Blazor.Input
@using C1.Blazor.ListView
@using C1.Blazor.DateTimeEditors
@using Newtonsoft.Json
@using C1.Blazor.Grid
@using System.Reflection
@inject IJSRuntime js

@using MauiBlazor.Data
@inject WeatherForecastService ForecastService

@*Styles*@
<style>
    .container {
        margin-left: 10px;
        margin-right: 10px;
    }

    .form-group {
        display: inline-flex !important;
        padding-bottom: 20px;
    }

        .form-group .popup-content-container {
            max-height: 300px;
        }

        .form-group label {
            justify-content: left;
            text-align: left;
            padding-right: 5px;
        }

    .datepicker {
        /*display: inline-flex !important;*/
    }

    .list-view-row {
        padding: 8px;
    }

    .c1-numeric-box {
        height: 38px;
        border-color: #ced4da;
    }

    .head-text {
        font-weight: bold;
        margin-bottom: 20px;
        padding-bottom: 20px;
    }
</style>

<div class="container ">
    <div style="width: 100%;">
        <div class="col-sm-12" style="padding-top: 15px;">
            <h3>Customer Information Screen</h3>
            <div style="padding-top: 15px;width:100%;">
                <span class="head-text">Find Customer's Orders: </span>
                <br />
                <br />
                <div class="form-inline">
                    <div class="form-group">
                        <label>Customer:</label>
                        <C1AutoComplete @ref="Customer" Placeholder="" ItemsSource="Customers" T="Customer"
                                        DisplayMemberPath="customerId" Class="form-control" Style="@("width:300px; margin-left: 50px; height: 38px;")" ShowButton="true"
                                        @bind-SelectedIndex="CustomerIndex"></C1AutoComplete>
                    </div>
                    <br />
                    <div class="form-group">
                        <label>Record Count:</label><C1NumericBox Min="1" Max="10" @bind-Value="RecordCount" Class="form-control" Style="@("width: 300px;height:38px;border-radius:4px; margin-left: 20px;")"></C1NumericBox>
                    </div>
                    <br />
                    <span style="width:28%;;">
                        <button class="btn btn-primary" @onclick="GetOrders">Get Orders</button>
                    </span>
                </div>
            </div>
        </div>

        @*Filter Orders*@
        <br />
        <span class="head-text">Search Orders:</span>
        <br />
        <br />
        <div class="form-inline">
            <div class="form-group">
                <C1TextBox @bind-Text="filterString" Placeholder="Search" Class="form-control" Style="@("height: 38px;")"></C1TextBox>
            </div>
        </div>
        <br />
    </div>

    @*FlexGrid*@
    <div>
        <FlexGrid ItemsSource="OrderItemsSource" AutoGenerateColumns="false" IsReadOnly="true" Style="@("border: 1px solid black;")"
                  DefaultColumnWidth="GridLength.Star" ColumnHeaderStyle="@("background-color:#778898;color:#fff;font-weight:bold")"
                  AlternatingRowStyle="@("background-color:#fff")"
                  RowStyle="@("background-color:#E5E6FA;color:#000")">
            <FlexGridBehaviors>
                <FullTextFilterBehavior MatchNumbers="true" HighlightStyle="@("color:#3E65FF")" FilterString="@filterString" TreatSpacesAsAndOperator="true"></FullTextFilterBehavior>
            </FlexGridBehaviors>
            <FlexGridColumns>
                <GridColumn Header="Order ID" Binding="OrderId" HorizontalAlignment="C1HorizontalAlignment.Center" HeaderHorizontalAlignment="C1HorizontalAlignment.Center" />
                <GridColumn Header="Order Date" Binding="OrderDate" Format="d" HorizontalAlignment="C1HorizontalAlignment.Center" HeaderHorizontalAlignment="C1HorizontalAlignment.Center" />
                <GridColumn Header="Customer ID" Binding="CustomerId" HorizontalAlignment="C1HorizontalAlignment.Center" HeaderHorizontalAlignment="C1HorizontalAlignment.Center" />
                <GridColumn Header="Employee Id" Binding="EmployeeId" HorizontalAlignment="C1HorizontalAlignment.Center" HeaderHorizontalAlignment="C1HorizontalAlignment.Center" />
                <GridColumn Header="Shipped Date" Binding="ShippedDate" Format="d" HorizontalAlignment="C1HorizontalAlignment.Center" HeaderHorizontalAlignment="C1HorizontalAlignment.Center" />
                <GridColumn Header="Required Date" Binding="RequiredDate" Format="d" HorizontalAlignment="C1HorizontalAlignment.Center" HeaderHorizontalAlignment="C1HorizontalAlignment.Center" />
                <GridColumn Header="Ship Address" Binding="ShipAddress" HorizontalAlignment="C1HorizontalAlignment.Center" HeaderHorizontalAlignment="C1HorizontalAlignment.Center" />
            </FlexGridColumns>
        </FlexGrid>
    </div>

</div>

@code {
    private WeatherForecast[] forecasts;

    string filterString;

    string _baseUrl = "<https://gc-demo-dataservice.azurewebsites.net/northwind/api/v1/Customers>";
    int CustomerIndex = 0;
    int PageFrom = 0;
    int RecordCount = 5;
    Order Order;

    C1AutoComplete<Customer> Customer;

    List<Customer> Customers = new List<Customer>();
    List<Order> Orders = new List<Order>();

    private Order[] CustomerOrder;

    private List<Order> OrderItemsSource = new List<Order>();

    protected override async Task OnInitializedAsync()
    {
        Customers = await GetCustomersAsync();
    }

    public async Task<List<Customer>> GetCustomersAsync()
    {
        HttpClient http = new HttpClient();
        var data = await http.GetStringAsync($"{_baseUrl}");
        return JsonConvert.DeserializeObject<List<Customer>>(data);
    }

    // Returns order for a customer
    public async Task<List<Order>> GetCustomersOrderAsync()
    {
        HttpClient http = new HttpClient();
        var data = await http.GetStringAsync($"{_baseUrl}/{Customers[Customer.SelectedIndex].customerId}/Orders");
        int len = data.Length;

        List<Order> result = JsonConvert.DeserializeObject<List<Order>>(data);
        if (result.Count < RecordCount)
        {
            js.InvokeVoidAsync("alert", $"{result.Count} records fetched from API.");
        }
        return result;
    }

    public async Task GetOrders()
    {
        var _orders = await GetCustomersOrderAsync();
        Orders = _orders.Skip(this.PageFrom).Take(this.RecordCount).ToList<Order>();
        OrderItemsSource = _orders.Skip(this.PageFrom).Take(this.RecordCount).ToList<Order>();
    }
}

This code snippet includes implementing the AutoComplete feature and a FlexGrid layout in a web page.

Next, create two data modal classes named Customer.cs and Order.cs in the data folder.

The code of Customer.cs will be:

namespace MauiBlazor.Data
{
    public class Customer
    {
        public string customerId { get; set; }
        public int employeeId { get; set; }

        public string orderDate { get; set; }
        public int orderId { get; set; }

        public string requiredDate { get; set; }

        public string shipAddress { get; set; }

        public string shipCity { get; set; }
        public string shipCountry { get; set; }
        public string shipName { get; set; }
        public string shipPostalCode { get; set; }

        public int shipVia { get; set; }
        public string shippedDate { get; set; }
        public string shipRegion { get; set; }

        //pub

        public string companyName { get; set; }
        public string contactName { get; set; }
        public string ContactTitle { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string Region { get; set; }
        public string PostalCode { get; set; }
        public string Country { get; set; }
        public string Phone { get; set; }
        public string Fax { get; set; }
    }
}

The code of Orde.cs will be:

namespace MauiBlazor.Data
{
    public class Order
    {
        public int OrderID { get; set; }
        public string CustomerId { get; set; }
        public int EmployeeId { get; set; }
        public DateTime OrderDate { get; set; }
        public DateTime RequiredDate { get; set; }
        public DateTime ShippedDate { get; set; }
        public int ShipVia { get; set; }
        public string ShipName { get; set; }
        public string ShipAddress { get; set; }
        public string ShipCity { get; set; }
        //public string ShipRegion { get; set; }
        public string ShipPostalCode { get; set; }
        public string ShipCountry { get; set; }
        //public string Source { get; set; }

        public Order()
        {

        }

    }
}

That's all you have to do. Now just run the application you, and you will see the out of data filtering feature like the image below:

Blazor Datagrid MAUI App

Running the Application on IOS Devices

We can add IOS devices in many ways, like we can connect the devices locally, or you can connect the devices remotely.

In this blog, we will discuss connecting the Mac devices remotely.

To set up the Mac build host, first, you need to enable remote login on the Mac system.

  1. On the Mac, open System Preferences and go to the Sharing pane.
  2. Check Remote Login in the Service list.

Blazor Datagrid Maui

Ensure that it's configured to allow access for All users or that your Mac username or group is included in the list of allowed users.

Connect to the Mac from Visual Studio 2022

1. Select Tools > iOS > Pair to Mac

You will see a window like the one below:

Blazor Datagrid Maui

2. Click on add Mac window like the one below will be opened.

Blazor Datagrid Maui

3. Enter the Ip of the Mac system (you may use ifconfig command to know the IP address on the host Mac machine)

4. You will be asked for a username and password.

5. Enter the username and password.

Blazor Datagrid Maui

6. Click on the login button.

7. Wait for the connection to finish. (Also note that the host machine should have Xcode installed)

8. Please wait for it to be complete. You will see the dialog now has one connected machine like below:

Blazor Datagrid Maui

9. Close the dialog.

10. Select the simulator device.

Blazor Datagrid Maui

11. Run the project.

Congratulations! You have successfully run the project on an IOS device. It will look something like the image below:

Blazor Datagrid Maui

Conclusion

In conclusion, Blazor MAUI is a powerful framework that enables developers to create native apps for multiple platforms using a single codebase. With its integration with GrapeCity's ComponentOne FlexGrid, developers can create high-quality, data-driven apps with rich visualization, editing, and manipulation capabilities.

This blog post covered the basic steps for creating a .NET MAUI Blazor app and integrating the Blazor FlexGrid control. We have also explored advanced techniques for customizing and extending the controls to meet specific requirements.

Ready to Start Building? Download ComponentOne Today!

comments powered by Disqus