Rows in WinUI DataGrid

1 Jul 202224 minutes to read

This section explains about various row types in SfDataGrid.

StackedHeaderRow

AddNewRow

SummaryRow

UnboundRow

Row Header

RowHeader is a special column used to indicate the status of row (current row, editing status, errors in row, etc.) which is placed as first cell of each row. You can show or hide the row header by setting SfDataGrid.ShowRowHeader property.

<dataGrid:SfDataGrid x:Name="sfDataGrid"
                       AddNewRowPosition="Top"
                       ItemsSource="{Binding Orders}"
                       ShowRowHeader="True" />
sfDataGrid.ShowRowHeader = true;

WinUI DataGrid Row Header

Row indicators and its description

Row Indicator Description
RowHeader in WinUI DataGrid Image2 Denotes the row which has current cell or selected item.
RowHeader in WinUI DataGrid Image3 Denotes row is being edited.
RowHeader in WinUI DataGrid Image4 Denotes row is AddNewRow.
RowHeader in WinUI DataGrid Image5 Denotes the row has errors or current row which has errors.

Row header width

You can change the width of the row header by setting SfDataGrid.RowHeaderWidth property.

<dataGrid:SfDataGrid x:Name="sfDataGrid"
                       ShowRowHeader="True"
                       RowHeaderWidth="50"
                       ItemsSource="{Binding Orders}" />
sfDataGrid.RowHeaderWidth = 50;

Display the row index in row header

You can display the corresponding row index in each row header, by customizing the ControlTemplate of GridRowHeaderCell. You have to bind the RowIndex property to TextBlock.Text like the below code example.

<Style TargetType="dataGrid:GridRowHeaderCell">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="dataGrid:GridRowHeaderCell">
                <Border x:Name="PART_RowHeaderCellBorder"
                        Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <Grid>
                        <TextBlock HorizontalAlignment="Center"
                                   VerticalAlignment="Center"
                                   Text="{Binding RowIndex,RelativeSource={RelativeSource TemplatedParent}}"
                                   TextAlignment="Center" />
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

WinUI DatGrid displays Row Header Cells with Row Index

Change the current row indicator

You can change the current row indicator in the row header by customizing the control template of GridRowHeaderCell.

<Style TargetType="dataGrid:GridRowHeaderCell">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="dataGrid:GridRowHeaderCell">
                <Border x:Name="PART_RowHeaderCellBorder"
                        Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="IndicationStates">
                            <VisualState x:Name="Normal">
                            </VisualState>
                            <VisualState x:Name="CurrentRow">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_RowHeaderIndicator" Storyboard.TargetProperty="Data">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Geometry>F1M-218.342,2910.79L-234.066,2926.52 -233.954,2926.63 -225.428,2926.63 -210.87,2912.07 -206.495,2907.7 -225.313,2888.88 -234.066,2888.88 -218.342,2904.6 -259.829,2904.6 -259.829,2910.79 -218.342,2910.79z</Geometry>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>                                            
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Path x:Name="PART_RowHeaderIndicator"
                          Width="8.146"
                          Height="8.146"
                          HorizontalAlignment="Center"
                          VerticalAlignment="Center"
                          Fill="#FF303030"
                          Stretch="Fill">
                    </Path>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Customizing Current Row Indicator in WinUI DataGrid

Header Row

Header row is present in top of the DataGrid which has column headers in it. Column header describes the caption to identify the column content.

WinUI DataGrid Header Row with Column Header

You can change the header row height by setting SfDataGrid.HeaderRowHeight property.

Hiding header row

You can hide the header row by setting SfDataGrid.HeaderRowHeight as 0 (zero).

<dataGrid:SfDataGrid x:Name="sfDataGrid"
                       HeaderRowHeight="0"
                       ItemsSource="{Binding Orders}" />

Hide Row Header in WinUI DataGrid

You can also hide the header row of DetailsViewDataGrid by setting HeaderRowHeight as 0 (zero) to ViewDefinition.DataGrid.

<dataGrid:SfDataGrid x:Name="sfDataGrid" ItemsSource="{Binding Orders}">
    <dataGrid:SfDataGrid.DetailsViewDefinition>
        <dataGrid:GridViewDefinition RelationalColumn="OrderDetails">
            <dataGrid:GridViewDefinition.DataGrid>
                <dataGrid:SfDataGrid x:Name="firstLevelNestedGrid" HeaderRowHeight="0" />
            </dataGrid:GridViewDefinition.DataGrid>
        </dataGrid:GridViewDefinition>
    </dataGrid:SfDataGrid.DetailsViewDefinition>
</dataGrid:SfDataGrid>

Hide Row Header of Details View in WinUI DataGrid

Freeze panes

DataGrid provides support to freeze the rows and columns at top and bottom similar to excel. You can freeze the rows and columns by setting following properties,

Property Name Description

FrozenRowsCount

Set the frozen rows count at top of the SfDataGrid.

FrozenFooterRowsCount

Set the footer rows count at bottom of the SfDataGrid.

FrozenColumnsCount

Set the frozen columns count in left side of the SfDataGrid.

FrozenFooterColumnsCount

Set the frozen columns in right side of the SfDataGrid.
<dataGrid:SfDataGrid x:Name="sfDataGrid"
                       FrozenFooterColumnsCount="1"
                       FrozenColumnsCount="1"
                       FrozenRowsCount="2"
                       FrozenFooterRowsCount="3"
                       ItemsSource="{Binding Orders}" />
sfDataGrid.FrozenFooterColumnsCount = 1;
sfDataGrid.FrozenColumnsCount = 1;
sfDataGrid.FrozenRowsCount = 2;
sfDataGrid.FrozenFooterRowsCount = 3;

WinUI DataGrid displays Frozen Rows and columns at top and bottom

Differentiate frozen rows from normal rows

You can differentiate the frozen rows and footer rows from normal rows by writing style for DataGridRowControl and by customizing the FrozenRow and FooterRow visual states.

<Style TargetType="dataGrid:DataGridRowControl">
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="BorderBrush" Value="Gray" />
    <Setter Property="BorderThickness" Value="0" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="dataGrid:DataGridRowControl">
                <Grid>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="BorderStates">
                            <VisualState x:Name="NormalRow" />
                            <VisualState x:Name="FrozenRow">
                                <Storyboard BeginTime="0">
                                    <ObjectAnimationUsingKeyFrames BeginTime="0"
                                                           Duration="1"
                                                           Storyboard.TargetName="PART_RowBorder"
                                                           Storyboard.TargetProperty="BorderThickness">

                                        <!--  Border Thickness for Frozen rows  -->
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="0, 0, 0, 4" />
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>

                            <VisualState x:Name="FooterRow">
                                <Storyboard BeginTime="0">
                                    <ObjectAnimationUsingKeyFrames BeginTime="0"
                                                           Duration="1"
                                                           Storyboard.TargetName="PART_RowBorder"
                                                           Storyboard.TargetProperty="BorderThickness">

                                        <!--  Border Thickness for Footer rows  -->
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="0, 4, 0, 0" />
                                    </ObjectAnimationUsingKeyFrames>

                                    <ObjectAnimationUsingKeyFrames BeginTime="0"
                                                           Duration="1"
                                                           Storyboard.TargetName="PART_RowBorder"
                                                           Storyboard.TargetProperty="Margin">

                                        <DiscreteObjectKeyFrame KeyTime="0" Value="0, -1, 0, 0" />
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>

                    <Border x:Name="PART_RowBorder"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}" />

                    <Rectangle x:Name="PART_CurrentFocusRow"
                               Margin="{TemplateBinding CurrentFocusBorderMargin}"
                               Stroke="DarkGray"
                               StrokeDashArray="3,3"
                               StrokeThickness="1"
                               Visibility="{TemplateBinding CurrentFocusRowVisibility}" />

                    <Rectangle x:Name="PART_RowBackgroundClipRect" Fill="{TemplateBinding Background}" />

                    <Border x:Name="PART_RowSelectionBorder"
                            Background="{TemplateBinding SelectionBackground}"
                            Visibility="{TemplateBinding SelectionBorderVisibility}" />

                    <Border x:Name="PART_RowHighlightBorder"
                            Margin="1"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Visibility="{TemplateBinding HighlightSelectionBorderVisibility}" />

                    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                        <ContentPresenter />
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Differentiating Frozen Rows and Footer Rows from Normal rows in WinUI DataGrid

Disable drag and drop between frozen and non-frozen columns

You can disable the drag and drop between frozen and non-frozen columns by handling ColumnDragging event.
Using Reason property in QueryColumnDraggingEventArgs, you can cancel the column dropping operation.

In the below code, if the Reason is QueryColumnDraggingReason.Dropping and the column is dragged from frozen region to non-frozen region or vice versa, you can cancel the dropping action by setting e.Cancel as true in the event.

this.sfDataGrid.ColumnDragging += SfDataGrid_ColumnDragging;

void SfDataGrid_ColumnDragging(object sender, QueryColumnDraggingEventArgs e)
{
    if (e.Reason == QueryColumnDraggingReason.Dropping)
    {
        //used to get frozen column index from the  frozen column count.
        var frozenColIndex = sfDataGrid.FrozenColumnsCount +
                                              this.sfDataGrid.ResolveToStartColumnIndex();
        //cancels dragging from frozen column to non-frozen column.

        if (e.From < frozenColIndex && e.To > frozenColIndex - 1)
            e.Cancel = true;

        // cancels dragging from non-frozen column to frozen column.

        if (e.From > frozenColIndex && e.To < frozenColIndex ||
             (e.From == frozenColIndex && e.To < frozenColIndex))
            e.Cancel = true;
    }
}

Limitations

  1. When using DetailsView with freeze panes, exception will be raised like DetailsView is not supported with Freeze panes support.

  2. When AllowFrozenGroupHeaders is true, frozen rows will not be considered.

  3. SfDataGrid has support to freeze the number of rows from top or bottom. There is no support to freeze a specific row.

NOTE

  1. Header rows, table summary rows and row header are frozen regardless of FrozenRowsCount and FrozenFooterRowsCount.
  2. FrozenRowsCount and FrozenFooterRowsCount values should be less than the number of rows and column visible.