Unbound column in MAUI DataGrid (SfDataGrid)

7 Jul 202614 minutes to read

The data grid allows adding additional columns that are not bound with data objects from the underlying data source. The unbound column can be added using the SfDataGrid.DataGridUnboundColumn class.

<ContentPage.BindingContext>
    <local:OrderInfoViewModel x:Name = "viewModel"/>
</ContentPage.BindingContext>

<syncfusion:SfDataGrid x:Name = "dataGrid"
                       ItemsSource = "{Binding Orders}"
                       AutoGenerateColumnsMode = "None">
    <syncfusion:SfDataGrid.Columns>
        <syncfusion:DataGridTextColumn MappingName = "Customer"
                                       HeaderText = "Customer"/>
        <syncfusion:DataGridNumericColumn MappingName = "Quantity"
                                          HeaderText = "Quantity"
                                          Format = "#"/>
        <syncfusion:DataGridNumericColumn MappingName = "UnitPrice"
                                          HeaderText = "Unit Price"
                                          Format = "C"/>
        <syncfusion:DataGridUnboundColumn MappingName = "TotalPrice"
                                          HeaderText = "Total"
                                          Expression = "UnitPrice*Quantity"
                                          Format = "C" />
    </syncfusion:SfDataGrid.Columns>
</syncfusion:SfDataGrid>
SfDataGrid dataGrid = new SfDataGrid();
OrderInfoViewModel viewModel = new OrderInfoViewModel();
dataGrid.ItemsSource = viewModel.Orders;
dataGrid.AutoGenerateColumnsMode = AutoGenerateColumnsMode.None;

var orderColumn = new DataGridTextColumn()
{
    MappingName = "Customer",
    HeaderText = "Customer",
};
dataGrid.Columns.Add(orderColumn);

var quantityColumn = new DataGridNumericColumn()
{
    MappingName = "Quantity",
    HeaderText = "Quantity",
    Format = "#",
};
dataGrid.Columns.Add(quantityColumn);

var unitPriceColumn = new DataGridNumericColumn()
{
    MappingName = "UnitPrice",
    HeaderText = "Unit Price",
    Format = "C",
};
dataGrid.Columns.Add(unitPriceColumn);

DataGridUnboundColumn totalColumn = new DataGridUnboundColumn()
{
    MappingName = "TotalPrice",
    HeaderText = "total",
    Expression = "UnitPrice*Quantity",
    Format = "C"
};
dataGrid.Columns.Add(totalColumn);

this.Content = dataGrid;

Unbound column in MAUI DataGrid

Note: It is mandatory to specify the DataGridColumn.MappingName for SfDataGrid.DataGridUnboundColumn with some name to identify the column. It is not necessary for this field to exist in the data object.

Populating data for the unbound column

Data for the unbound column can be configured using one of two approaches:

  1. Expression property — for simple arithmetic and logical calculations
  2. QueryUnboundColumnValue event — for complex logic and custom data retrieval

Using Expression

The arithmetic or logical expression can be specified using the Expression property to compute the display value. By default, DataGridUnboundColumn evaluates expressions with case sensitivity. Disable case sensitivity by setting the CaseSensitive property to false.

Arithmetic operations Operator Usage in Expression
Add + `UnitPrice + Tax`
Subtract - `Price - Discount`
Multiply * `UnitPrice * Quantity`
Divide / `Total / ItemCount`
Power ^ `Value ^ 2`
Mod % `Quantity % 12`
Greater Than > `Price > 1000`
Less than < `Quantity < 10`
Equal = `Status = 'Active'`
Greater Than or Equal >= `Rating >= 4`
Less Than or Equal <= `Age <= 18`
Logical operations Character Code Usage in Expression
AND (char)135 `(Quantity > 10)(char)135(UnitPrice > 100)`
OR (char)136 `(Quantity > 10)(char)136(UnitPrice > 100)`
NOT (char)137 `(char)137(IsApproved)`

Using QueryUnboundColumnValue event

The QueryUnboundColumnValue event fires when a value for the unbound column is requested. It provides information about the cell that triggered this event, allowing you to set custom values for unbound column cells. This event is triggered with DataGridUnboundColumnEventArgs.

The DataGridUnboundColumnEventArgs provides the following properties:

  • Column: Gets the DataGridColumn of the cell that triggers this event.
  • OriginalSender: Gets the data grid instance raising the event.
  • Record: Gets the underlying row data object.
  • UnboundAction: Defines the action that triggered the event.
  • Value: Gets or sets the value for the DataGridUnboundColumn cell based on the UnboundAction.

Populate the data for the unbound column by handling the QueryUnboundColumnValue event, which allows customizing the value of the DataGridUnboundColumn. The DataGridUnboundColumnEventArgs exposes the Value property, allowing you to set values for unbound column cells based on the UnboundAction.

Refer to the following code example in which data for the unbound column is populated by handling the QueryUnboundColumnValue event:

<ContentPage.BindingContext>
    <local:OrderInfoViewModel x:Name = "viewModel"/>
</ContentPage.BindingContext>

<syncfusion:SfDataGrid x:Name = "dataGrid"
                       ItemsSource = "{Binding Orders}"
                       QueryUnboundColumnValue = "DataGrid_QueryUnboundColumnValue"
                       AutoGenerateColumnsMode = "None">
    <syncfusion:SfDataGrid.Columns>
        <syncfusion:DataGridTextColumn MappingName = "Customer"
                                       HeaderText = "Customer"/>
        <syncfusion:DataGridNumericColumn MappingName = "Quantity"
                                          HeaderText = "Quantity"
                                          Format = "#"/>
        <syncfusion:DataGridNumericColumn MappingName = "UnitPrice"
                                          HeaderText = "Unit Price"
                                          Format = "C"/>
        <syncfusion:DataGridUnboundColumn MappingName = "TotalPrice"
                                          HeaderText = "Total"/>
    </syncfusion:SfDataGrid.Columns>
</syncfusion:SfDataGrid>
SfDataGrid dataGrid = new SfDataGrid();
OrderInfoViewModel viewModel = new OrderInfoViewModel();
dataGrid.ItemsSource = viewModel.Orders;
dataGrid.QueryUnboundColumnValue += DataGrid_QueryUnboundColumnValue;
dataGrid.AutoGenerateColumnsMode = AutoGenerateColumnsMode.None;

var orderColumn = new DataGridTextColumn()
{
    MappingName = "Customer",
    HeaderText = "Customer",
};
dataGrid.Columns.Add(orderColumn);

var quantityColumn = new DataGridNumericColumn()
{
    MappingName = "Quantity",
    HeaderText = "Quantity",
    Format = "#",
};
dataGrid.Columns.Add(quantityColumn);

var unitPriceColumn = new DataGridNumericColumn()
{
    MappingName = "UnitPrice",
    HeaderText = "Unit Price",
    Format = "C",
};
dataGrid.Columns.Add(unitPriceColumn);

DataGridUnboundColumn totalColumn = new DataGridUnboundColumn()
{
    MappingName = "TotalPrice",
    HeaderText = "total",
};
dataGrid.Columns.Add(totalColumn);

this.Content = dataGrid;
private void DataGrid_QueryUnboundColumnValue(object? sender, DataGridUnboundColumnEventArgs e)
{
    if (e.UnboundAction == DataGridUnboundActions.QueryData)
    {
        var recordType = e.Record?.GetType();
        if (recordType == null)
            return;

        var unitPriceProperty = recordType.GetProperty("UnitPrice");
        var quantityProperty = recordType.GetProperty("Quantity");

        if (unitPriceProperty == null || quantityProperty == null)
            return;

        var unitPriceValue = unitPriceProperty.GetValue(e.Record);
        var quantityValue = quantityProperty.GetValue(e.Record);

        if (unitPriceValue != null && quantityValue != null &&
            decimal.TryParse(unitPriceValue.ToString(), out decimal unitPrice) &&
            int.TryParse(quantityValue.ToString(), out int quantity))
        {
            decimal total = unitPrice * quantity;
            e.Value = total.ToString("C");
        }
    }
}