How to Build a Blazor Datagrid in Your MAUI Application

MESCIUS inc.
MESCIUS inc.
Published in
10 min readMar 13, 2023

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

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:

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

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

In the Configure your new project dialog:

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

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

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

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

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:

Integrate Flexgrid for Blazor

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

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

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

Import the C1.Blazor.Grid at the top.

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.

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>

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:

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 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; }
}
}

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:

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.

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:

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

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.

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:

9. Close the dialog.

10. Select the simulator device.

11. Run the project.

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

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.

Originally published at https://www.developer.mescius.com on March 13, 2023.

--

--

MESCIUS inc.
MESCIUS inc.

We provide developers with the widest range of Microsoft Visual Studio components, IDE platform development tools, and applications.