Unbound Row in .NET MAUI DataGrid (SfDataGrid)

7 Jul 202614 minutes to read

The .NET MAUI DataGrid allows you to add additional rows at top and also bottom of the DataGrid which are not bound with data object of underlying data source. You can add unbound rows using SfDataGrid.UnboundRows collection property. You can add any number of unbound rows to the DataGrid. Unbound rows can also be exported to PDF and Excel documents.

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

<syncfusion:SfDataGrid x:Name = "dataGrid"
                       ItemsSource = "{Binding Orders}">
    <syncfusion:SfDataGrid.UnboundRows>
        <syncfusion:DataGridUnboundRow Position = "Top"/>
    </syncfusion:SfDataGrid.UnboundRows>
</syncfusion:SfDataGrid>
SfDataGrid dataGrid = new SfDataGrid();
OrderInfoViewModel viewModel = new OrderInfoViewModel();
dataGrid.ItemsSource = viewModel.Orders;
var unboundRow = new DataGridUnboundRow()
{
    Position = DataGridUnboundRowPosition.Top,
};
dataGrid.UnboundRows.Add(unboundRow);
this.Content = dataGrid;

Unbound Rows

Positioning unbound rows

Unbound row can be placed in top or bottom of the DataGrid by setting the desired value to the DataGridUnboundRow.Position property.

Below table shows the available unbound row positions.

UnboundRowPosition Position in DataGrid
FixedTop Unbound row placed at top, right below the header row. In this position, unbound row is not selectable, not editable and frozen when scrolling.
Top Unbound row placed at top, right above the record rows. In this position, unbound row is selectable, editable and scrollable.
Bottom Unbound row placed at bottom, right below record rows. In this position, unbound row is selectable, editable and scrollable.
FixedBottom Unbound row placed at bottom of SfDataGrid. In this position, unbound row is not selectable, not editable and frozen when scrolling.

Below screenshot shows different unbound rows placed in all possible positions.

Positioning unbound rows

Populating data for unbound rows

You can populate data for the unbound row by handling QueryUnboundRow event of .NET MAUI DataGrid. This event is fired for each cell of the unbound rows whenever the row gets refreshed or comes to view.
DataGridUnboundRowEventArgs of the QueryUnboundRow event provides information about the cell that triggered this event.

You can get or set the DataGridUnboundRowEventArgs.Value property based on the DataGridUnboundActions. If UnboundAction is QueryData then you can set the value to be displayed. If the UnboundAction is CommitData then you can get the edited value.

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

<syncfusion:SfDataGrid x:Name = "dataGrid"
                       ItemsSource = "{Binding Orders}"
                       SelectionMode = "Single"
                       SelectedIndex = "2"
                       QueryUnboundRow = "Datagrid_QueryUnboundRow"
                       SelectionChanged = "Datagrid_SelectionChanged">
    <syncfusion:SfDataGrid.UnboundRows>
        <syncfusion:DataGridUnboundRow Position = "Top"/>
    </syncfusion:SfDataGrid.UnboundRows>
</syncfusion:SfDataGrid>
SfDataGrid dataGrid = new SfDataGrid();
OrderInfoViewModel viewModel = new OrderInfoViewModel();
dataGrid.ItemsSource = viewModel.Orders;
dataGrid.SelectionMode = DataGridSelectionMode.Single;
dataGrid.SelectedIndex = 2;
dataGrid.QueryUnboundRow += Datagrid_QueryUnboundRow;
dataGrid.SelectionChanged += Datagrid_SelectionChanged;
var unboundRow = new DataGridUnboundRow()
{
    Position = DataGridUnboundRowPosition.Top,
};
dataGrid.UnboundRows.Add(unboundRow);
this.Content = dataGrid;

For example, now unbound row populated based on selected items in SfDataGrid.

private void Datagrid_SelectionChanged(object? sender, DataGridSelectionChangedEventArgs e)
{
    dataGrid!.InvalidateUnboundRow(dataGrid!.UnboundRows[0]);
}

private void Datagrid_QueryUnboundRow(object? sender, DataGridUnboundRowEventArgs e)
{
    if (dataGrid.CurrentRow is not OrderInfo currentOrder)
        return;

    if (e.RowColumnIndex.ColumnIndex == 0)
    {
        e.Value = currentOrder.OrderID;
    }
    else if (e.RowColumnIndex.ColumnIndex == 1)
    {
        e.Value = currentOrder.Customer;
    }
    else if (e.RowColumnIndex.ColumnIndex == 2)
    {
        e.Value = currentOrder.City;
    }
    else if (e.RowColumnIndex.ColumnIndex == 3)
    {
        e.Value = currentOrder.Country;
    }
    e.Handled = true;
}

Populating data for unbound rows

Refreshing the unbound rows at runtime

Add or remove unbound rows at runtime

You can add or remove unbound rows dynamically using the SfDataGrid.UnboundRows collection property. Changes reflect in the UI immediately.

SfDataGrid dataGrid = new SfDataGrid();
OrderInfoViewModel viewModel = new OrderInfoViewModel();
dataGrid.ItemsSource = viewModel.Orders;
dataGrid.SelectionMode = DataGridSelectionMode.Single;
dataGrid.SelectionChanged += Datagrid_SelectionChanged;

// Add a new unbound row
var unboundRow = new DataGridUnboundRow()
{
    Position = DataGridUnboundRowPosition.Top,
};
dataGrid.UnboundRows.Add(unboundRow);

//Remove an unbound row
dataGrid.UnboundRows.RemoveAt(0);

this.Content = dataGrid;

Refresh unbound row data programmatically

You can trigger the QueryUnboundRow event for specific unbound row cells at runtime by calling the SfDataGrid.InvalidateUnboundRow method. This refreshes the unbound row data without recreating it.

Here in the below code example, we have invalidated the unbound rows whenever selection is changed in the DataGrid.

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

<syncfusion:SfDataGrid x:Name = "dataGrid"
                       ItemsSource = "{Binding Orders}"
                       SelectionMode = "Single"
                       SelectionChanged = "Datagrid_SelectionChanged">
    <syncfusion:SfDataGrid.UnboundRows>
        <syncfusion:DataGridUnboundRow Position = "Top"/>
    </syncfusion:SfDataGrid.UnboundRows>
</syncfusion:SfDataGrid>
SfDataGrid dataGrid = new SfDataGrid();
OrderInfoViewModel viewModel = new OrderInfoViewModel();
dataGrid.ItemsSource = viewModel.Orders;
dataGrid.SelectionMode = DataGridSelectionMode.Single;
dataGrid.SelectionChanged += Datagrid_SelectionChanged;
var unboundRow = new DataGridUnboundRow()
{
    Position = DataGridUnboundRowPosition.Top,
};
dataGrid.UnboundRows.Add(unboundRow);
this.Content = dataGrid;
private void Datagrid_SelectionChanged(object? sender, DataGridSelectionChangedEventArgs e)
{
    dataGrid.InvalidateUnboundRow(dataGrid.UnboundRows[0]);
}

Editing in unbound rows

Cancel the editing for unbound row cell

You can cancel the editing of unbound row cell in the event handler of SfDataGrid.CurrentCellBeginEdit event with the help of SfDataGrid.GetUnboundRowAtRowIndex method and row index.

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

<syncfusion:SfDataGrid x:Name = "dataGrid"
                       ItemsSource = "{Binding Orders}"
                       AllowEditing = "True"
                       SelectionMode = "Single"
                       CurrentCellBeginEdit = "DataGrid_CurrentCellBeginEdit">
    <syncfusion:SfDataGrid.UnboundRows>
        <syncfusion:DataGridUnboundRow Position = "Top"/>
    </syncfusion:SfDataGrid.UnboundRows>
</syncfusion:SfDataGrid>
SfDataGrid dataGrid = new SfDataGrid();
OrderInfoViewModel viewModel = new OrderInfoViewModel();
dataGrid.ItemsSource = viewModel.Orders;
dataGrid.AllowEditing = true;
dataGrid.SelectionMode = DataGridSelectionMode.Single;
dataGrid.CurrentCellBeginEdit += DataGrid_CurrentCellBeginEdit;
var unboundRow = new DataGridUnboundRow()
{
    Position = DataGridUnboundRowPosition.Top,
};
dataGrid.UnboundRows.Add(unboundRow);
this.Content = dataGrid;
private void DataGrid_CurrentCellBeginEdit(object sender, DataGridCurrentCellBeginEditEventArgs e)
{
    var unboundRow = dataGrid.GetUnboundRowAtRowIndex(e.RowColumnIndex.RowIndex);

    if (unboundRow == null)
        return;
    e.Cancel = true;
}

Saving edited unbound row cell value to external source

You can get the edited value of unbound row cells from DataGridUnboundRowEventArgs.Value property in the QueryUnboundRow event when UnboundAction is CommitData.

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

<syncfusion:SfDataGrid x:Name = "dataGrid"
                       ItemsSource = "{Binding Orders}"
                       AllowEditing = "True"
                       SelectionMode = "Single"
                       QueryUnboundRow = "Datagrid_QueryUnboundRow">
    <syncfusion:SfDataGrid.UnboundRows>
        <syncfusion:DataGridUnboundRow Position = "Top" />
    </syncfusion:SfDataGrid.UnboundRows>
</syncfusion:SfDataGrid>
SfDataGrid dataGrid = new SfDataGrid();
OrderInfoViewModel viewModel = new OrderInfoViewModel();
dataGrid.ItemsSource = viewModel.Orders;
dataGrid.AllowEditing = true;
dataGrid.SelectionMode = DataGridSelectionMode.Single;
dataGrid.QueryUnboundRow += Datagrid_QueryUnboundRow;
var unboundRow = new DataGridUnboundRow()
{
    Position = DataGridUnboundRowPosition.Top,
};
dataGrid.UnboundRows.Add(unboundRow);
this.Content = dataGrid;
private void Datagrid_QueryUnboundRow(object? sender, DataGridUnboundRowEventArgs e)
{
    if (e.UnboundAction == DataGridUnboundActions.CommitData)
    {
       var editedValue = e.Value;
    }
}

Changing unbound row height

You can change the height of unbound row using SfDataGrid.QueryRowHeight event.

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

<syncfusion:SfDataGrid x:Name = "dataGrid"
                       ItemsSource = "{Binding Orders}"
                       QueryRowHeight = "DataGrid_QueryRowHeight">
    <syncfusion:SfDataGrid.UnboundRows>
        <syncfusion:DataGridUnboundRow Position = "Top" />
    </syncfusion:SfDataGrid.UnboundRows>
</syncfusion:SfDataGrid>
SfDataGrid dataGrid = new SfDataGrid();
OrderInfoViewModel viewModel = new OrderInfoViewModel();
dataGrid.ItemsSource = viewModel.Orders;
dataGrid.QueryRowHeight += DataGrid_QueryRowHeight;
var unboundRow = new DataGridUnboundRow()
{
    Position = DataGridUnboundRowPosition.Top,
};
dataGrid.UnboundRows.Add(unboundRow);
this.Content = dataGrid;
private void DataGrid_QueryRowHeight(object? sender, DataGridQueryRowHeightEventArgs e)
{
    if (dataGrid.IsUnboundRow(e.RowIndex))
    {
        e.Height = 60;
        e.Handled = true;
    }
}

Changing unbound row height

Get unbound row

The unbound row can be obtained by using the GetUnboundRowAtRowIndex method. Returns a DataGridUnboundRow object if an unbound row exists at the specified index; otherwise returns null.

var unboundRow = dataGrid.GetUnboundRowAtRowIndex(1);
if (unboundRow != null)
{
    // Unbound row found
}