Easily Bind DataTable and Perform CRUD Actions with .NET MAUI DataGrid

Jollen Moyani - Aug 5 - - Dev Community

TL;DR: Discover how the .NET MAUI DataGrid control lets you bind a datatable, edit data directly, and even perform CRUD actions (Create, Read, Update, Delete)- all within the grid itself. Simplify data management in your .NET MAUI apps!

Syncfusion .NET MAUI DataGrid is used to display and manipulate data in a tabular view. Its rich feature set includes different column types, sorting, autofit columns and rows, and styling all elements. You can seamlessly bind data from various local and remote data sources, such as JSON, OData, WCF, and RESTful web services.

In this blog, we’ll see how to bind a datatable to the .NET MAUI DataGrid and perform CRUD (Create, Read, Update, Delete) operations within the datatable.

Note: Before proceeding, refer to the .NET MAUI DataGrid getting started documentation.

Binding datatable data to the .NET MAUI DataGrid

In this demo, we’ll showcase how to integrate data from a datatable named CustomerInfoTable into the Syncfusion .NET MAUI DataGrid control. This process involves binding the CustomerInfoTable data to the DataGrid and populating it, offering a practical example of seamless data presentation and manipulation within a .NET MAUI app.

Populate datatable in ViewModel

First, create a CustomerInfoTable with rows and columns, as shown in the following code example.

internal class DataSource
{
    internal DataTable CustomerInfoTable { get; set; }
    public DataSource() 
    {            
        CustomerInfoTable = GetDataTable();
        CustomerInfoTable.TableName = "CustomerInfo";
    }

    internal DataTable GetDataTable()
    {
        DataTable dataTable = new DataTable();
        dataTable.Columns.Add("OrderID", typeof(double));
        dataTable.Columns.Add("CustomerName", typeof(string));
        dataTable.Columns.Add("CustomerID", typeof(string));
        dataTable.Columns.Add("Country", typeof(string));
        dataTable.Rows.Add(1001, "Maria Anders", "ALFKI", "Germany");
        dataTable.Rows.Add(1002, "Ana Trujilo", "ANATR", "Mexico");
        dataTable.Rows.Add(1003, "Antonio Moreno", "ENDGY", "Mexico");
        dataTable.Rows.Add(1004, "Thomas Hardy", "ANTON", "UK");
        dataTable.Rows.Add(1005, "Christina Berglund", "BERGS", "Sweden");
        dataTable.Rows.Add(1006, "Hanna Moos", "BLAUS", "Germany");
        dataTable.Rows.Add(1007, "Frederique Citeaux", "BLONP", "France");
        dataTable.Rows.Add(1008, "Martin Sommer", "BOLID", "Spain");
        dataTable.Rows.Add(1009, "Laurence Lebihan", "BONAP", "France");
        dataTable.Rows.Add(1010, "Kathryn", "BOTTM", "Canada");
        dataTable.Rows.Add(1011, "Tamer", "XDKLF", "UK");
        dataTable.Rows.Add(1012, "Martin", "QEUDJ", "US");
        dataTable.Rows.Add(1013, "Nancy", "ALOPS", "France");
        dataTable.Rows.Add(1014, "Janet", "KSDIO", "Canada");
        dataTable.Rows.Add(1015, "Dodsworth", "AWSDE", "Canada");
        dataTable.Rows.Add(1016, "Buchanan", "CDFKL", "Germany");
        dataTable.Rows.Add(1017, "Therasa", "WSCJD", "Canada");
        dataTable.Rows.Add(1018, "Margaret", "PLSKD", "UK");
        dataTable.Rows.Add(1019, "Anto", "CCDSE", "Sweden");
        dataTable.Rows.Add(1020, "Edward", "EWUJG", "Germany");
        dataTable.Rows.Add(1021, "Anne", "AWSDK", "US");
        dataTable.Rows.Add(1022, "Callahan", "ODKLF", "UK");
        dataTable.Rows.Add(1023, "Vinet", "OEDKL", "France");
        return dataTable;
    }
}
Enter fullscreen mode Exit fullscreen mode

Then, define the DataView instance in the ViewModel to achieve data operations.

public class ViewModel : INotifyPropertyChanged
{
    private DataView customerInfoView;

    public ViewModel()
    {                      
        // DataSource.                 
        DataSource = new DataSource();
        CustomerInfoView = new DataView();
        CustomerInfoView.Table = DataSource.CustomerInfoTable;
    }

    public event PropertyChangedEventHandler? PropertyChanged;

    // DataGrid source.
    public DataView CustomerInfoView
    {
        get { return customerInfoView; }
        set
        {
            customerInfoView = value;
            RaisePropertyChanged("CustomerInfoView");
        }
    }

    internal DataSource DataSource { get; set; }    

    private void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }        
}
Enter fullscreen mode Exit fullscreen mode

Binding the ItemsSource on the XAML page

Let’s bind the data source to the .NET MAUI DataGrid (SfDataGrid) by setting its ItemsSource property.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:syncfusion="clr-namespace:Syncfusion.Maui.DataGrid;assembly=Syncfusion.Maui.DataGrid"
             xmlns:data="clr-namespace:Syncfusion.Maui.Data;assembly=Syncfusion.Maui.Data"
             xmlns:local="clr-namespace:DataGridMAUI"
             x:Class="DataGridMAUI.MainPage">
 <ContentPage.BindingContext>
  <local:ViewModel/>
 </ContentPage.BindingContext>

 <StackLayout>
  <syncfusion:SfDataGrid ColumnWidthMode="Fill"                          
                         ItemsSource="{Binding CustomerInfoView}">
  </syncfusion:SfDataGrid>
 </StackLayout>
</ContentPage>
Enter fullscreen mode Exit fullscreen mode

After executing the above code, you will get the following output.

Binding datatable data to .NET MAUI DataGrid control

Binding datatable data to .NET MAUI DataGrid control

Performing CRUD actions on datatable data in .NET MAUI DataGrid

Let’s explore how to perform CRUD (Create, Read, Update, Delete) actions on the datatable and update the changes in the .NET MAUI DataGrid control.

Here, we’ll design an EditPage to add, update, and delete the CustomerInfoTable details. To enable these actions on this page, we need to implement the code on the DataTable and define the commands in the ViewModel class, as mentioned in the following sections.

Implementing CRUD operations with datatable

Refer to the following code example to implement the code for manipulating the data on the edit page to update the data table.

internal class DataSource
{
    internal DataTable CustomerInfoTable { get; set; }
    public DataSource()
    {
        CustomerInfoTable = GetDataTable();
        CustomerInfoTable.TableName = "CustomerInfo";
    }
    internal void AddNewItem(CustomerInfo DataFormObject)
    {
        var dataRow = CustomerInfoTable.NewRow();
        dataRow.SetField("OrderID", DataFormObject.OrderID);
        dataRow.SetField("CustomerID", DataFormObject.CustomerID);
        dataRow.SetField("CustomerName", DataFormObject.CustomerName);
        dataRow.SetField("Country", DataFormObject.Country);
        CustomerInfoTable.Rows.Add(dataRow);
    }
    internal void OnDeleteItem(DataRow selectedItem)
    {
        CustomerInfoTable.Rows.Remove(selectedItem);
    }
    internal void OnSaveItem(DataRow selectedItem, CustomerInfo customerInfo)
    {
        if (selectedItem == null)
            return;
        selectedItem.SetField("OrderID", customerInfo.OrderID);
        selectedItem.SetField("CustomerID", customerInfo.CustomerID);
        selectedItem.SetField("CustomerName", customerInfo.CustomerName);
        selectedItem.SetField("Country", customerInfo.Country);
    }
    internal void EditCustomerInfo(CustomerInfo customerInfo, DataRow dataRow)
    {
        customerInfo.OrderID = (double)dataRow["OrderID"];
        customerInfo.CustomerID = (string)dataRow["CustomerID"];
        customerInfo.CustomerName = (string)dataRow["CustomerName"];
        customerInfo.Country = (string)dataRow["Country"];
    }
}
Enter fullscreen mode Exit fullscreen mode

Implementing CRUD commands in the ViewModel class

Let’s define the commands to add a new item, edit an item, or delete a selected item in the ViewModel.cs file.

Refer to the following code example.

public class ViewModel : INotifyPropertyChanged
{
    private DataView customerInfoView;

    public ViewModel()
    {                      
        // DataSource.                 
        DataSource = new DataSource();

        // CRUD operations.
        CreateCustomerCommand = new Command(OnCreateCustomerInfo);
        EditCustomerCommand = new Command<object>(OnEditCustomerInfo);
        SaveItemCommand = new Command(OnSaveItem);
        DeleteItemCommand = new Command(OnDeleteItem);
        AddItemCommand = new Command(OnAddNewItem);
    }


    public event PropertyChangedEventHandler? PropertyChanged;

    // Data operations commands.
    public Command CreateCustomerCommand { get; set; }
    public Command<object> EditCustomerCommand { get; set; }
    public Command SaveItemCommand { get; set; }
    public Command DeleteItemCommand { get; set; }
    public Command AddItemCommand { get; set; }

    #region CRUD commands
    private async void OnAddNewItem()
    {                     
        DataSource.AddNewItem(DataFormObject);
        await Application.Current.MainPage.Navigation.PopAsync();
    }
    private async void OnDeleteItem()
    {            
        DataSource.OnDeleteItem(SelectedItem);
        await Application.Current.MainPage.Navigation.PopAsync();
    }
    private async void OnSaveItem()
    {
        DataSource.OnSaveItem(SelectedItem, DataFormObject);
        await Application.Current.MainPage.Navigation.PopAsync();
    }
    private void OnEditCustomerInfo(object obj)
    {
        SelectedItem = ((obj as Syncfusion.Maui.DataGrid.DataGridCellTappedEventArgs).RowData as DataRowView).Row;
        DataFormObject = new CustomerInfo();
        DataSource.EditCustomerInfo(DataFormObject, SelectedItem);
        var editPage = new EditPage();
        editPage.BindingContext = this;
        Application.Current.MainPage.Navigation.PushAsync(editPage);
    }
    private async void OnCreateCustomerInfo()
    {
        DataFormObject = new CustomerInfo();
        var editPage = new EditPage();
        editPage.BindingContext = this;
        await Application.Current.MainPage.Navigation.PushAsync(editPage);
    }
    #endregion

    private void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }        
}
Enter fullscreen mode Exit fullscreen mode

Binding ViewModel commands to the EditPage

To design the EditPage, we’ll use the Syncfusion .NET MAUI DataForm control. Then, we’ll bind the commands from the ViewModel class to this control. To edit the selected item in the list view and save the changes back to the SQLite database, set the CommitMode property to PropertyChanged.

Refer to the following code example.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:dataForm="clr-namespace:Syncfusion.Maui.DataForm;assembly=Syncfusion.Maui.DataForm"
             Title="Edit Page"
             x:Class="DataGridMAUI.EditPage">
 <Grid RowDefinitions="0.9*, 1, 0.1*">
  <dataForm:SfDataForm DataObject="{Binding DataFormObject}" CommitMode="PropertyChanged"/>
  <Border Grid.Row="1" Background="#F5F5F5"/>
  <Grid HeightRequest="50" Grid.Row="2" ColumnDefinitions="*,auto">
   <Button Text="Add" Grid.Column="0" Margin="15,0,5,0" Command="{Binding AddItemCommand}" HorizontalOptions="Start" VerticalOptions="Center"/>
   <HorizontalStackLayout HorizontalOptions="End" Grid.Column="1">
    <Button Text="Save" Grid.Column="1" HorizontalOptions="Center" VerticalOptions="Center" Command="{Binding SaveItemCommand}" />
    <Button Text="Delete" Grid.Column="2" Command="{Binding DeleteItemCommand}" VerticalOptions="Center" HorizontalOptions="Center"/>
   </HorizontalStackLayout>
  </Grid>
 </Grid>
</ContentPage>
Enter fullscreen mode Exit fullscreen mode

After executing the above code example, we’ll get the following output.

Designing the EditPage using .NET MAUI DataForm control

Designing the EditPage using .NET MAUI DataForm control

On tapping an item, you will get an edit page to change values or delete the tapped item. We’ve also added an icon (+) in the bottom-right corner of the .NET MAUI DataGrid to easily add a new item to the list.

Refer to the following GIF image.

Performing CRUD actions on the datatable using .NET MAUI DataGrid

Performing CRUD actions on the datatable using .NET MAUI DataGrid

Other data operations

The DataGrid also offers various other data operations to manipulate and explore its data. These options include:

  • Sorting
  • Grouping
  • Filtering

Let’s explore them in brief!

Sorting

You can arrange columns in the .NET MAUI DataGrid using built-in options like multicolumn sorting and tri-state sorting. However, note that custom sorting is not supported.

In the following image, the DataGrid is sorted in ascending order based on the Customer Name column.

Sorting datatable data using .NET MAUI DataGrid

Sorting datatable data using .NET MAUI DataGrid

Grouping

You can group the data in the .NET MAUI DataGrid in a hierarchical structure, organizing it based on the matching field values. Additionally, the DataGrid supports multi-grouping and custom grouping functionalities.

Refer to the following image.

Grouping datatable data using .NET MAUI DataGrid

Grouping datatable data using .NET MAUI DataGrid

Filtering

DataGrid’s built-in view doesn’t provide support for filtering in the DataTable class. However, we can effectively filter records using the DataTable’s DataView.RowFilter property. This feature allows for efficient and customized data filtering within the datatable.

Refer to the following image.

Filtering datatable data using .NET MAUI DataGrid

Filtering datatable data using .NET MAUI DataGrid

GitHub reference

For more details, refer to binding datatable and performing CRUD actions in the .NET MAUI DataGrid GitHub demo.

Conclusion

Thanks for reading! In this blog, we’ve seen how to bind datatable data to Syncfusion .NET MAUI DataGrid and perform CRUD actions in it. Try out the steps in this blog and leave your feedback in the comments section give below!

For current customers, the newest version of Essential Studio for .NET MAUI is available from the License and Downloads page. If you are not a Syncfusion customer, you can always download our free evaluation to see all our controls.

You can also contact us through our support forum, support portal, or feedback portal. As always, we are happy to assist you!

Relate blogs

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .