Rows in WPF DataGrid (SfDataGrid)
10 Nov 202324 minutes to read
This section explains about various row types in WPF DataGrid (SfDataGrid).
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.
<syncfusion:SfDataGrid x:Name="dataGrid"
AddNewRowPosition="Top"
ItemsSource="{Binding Orders}"
ShowRowHeader="True">
dataGrid.ShowRowHeader = true;
See also.
Customizing RowHeader based on record
Row indicators and its description
Row Indicator | Description |
---|---|
Denotes the row which has current cell or selected item. | |
Denotes row is being edited. | |
Denotes row is AddNewRow. | |
Denotes the row has errors. | |
Denotes that the current row which has errors. |
Row header width
You can change the width of the row header by setting SfDataGrid.RowHeaderWidth property.
<syncfusion:SfDataGrid x:Name="dataGrid"
ShowRowHeader="True"
RowHeaderWidth="50"
ItemsSource="{Binding Orders}" />
dataGrid.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="syncfusion:GridRowHeaderCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="syncfusion: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>
You can get the sample from here.
Change the current row indicator
You can change the CurrentRowIndicator in the row header by customizing the control template of GridRowHeaderCell
.
<Style TargetType="syncfusion:GridRowHeaderCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="syncfusion: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>
You can get the sample from here.
Change the background of row header
You can change the background color of the row header by customizing the style of the GridRowHeaderCell
. You can change the background color with the converter based on the underlying collection.
<Application.Resources>
<local:CustomConverter x:Key="converter"/>
<!--Customizing the RowHeader style-->
<Style TargetType= "syncfusion:GridRowHeaderCell">
<!--By using converter the Background color is changed based on the business logic-->
<Setter Property="Background" Value="{Binding Converter={StaticResource converter }}"/>
</Style>
</Application.Resources>
public class CustomConverter:IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
//Type casting the value as Data class(Business logic)
var data = value as Data;
//The Red color is applied to RowHeader if the status value is true otherwise the white color is applied
if (data.Status == true)
return Brushes.Red;
else
return Brushes.Green;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
You can get the sample from here.
Header Row
Header row is present in top of the WPF DataGrid which has column headers in it. Column header describes the caption to identify the column content.
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).
<syncfusion:SfDataGrid x:Name="dataGrid"
HeaderRowHeight="0"
ItemsSource="{Binding Orders}">
You can also hide the header row of DetailsViewDataGrid by setting HeaderRowHeight
as 0
(zero) to ViewDefinition.DataGrid.
<syncfusion:SfDataGrid x:Name="dataGrid" ItemsSource="{Binding Orders}">
<syncfusion:SfDataGrid.DetailsViewDefinition>
<syncfusion:GridViewDefinition RelationalColumn="Details">
<syncfusion:GridViewDefinition.DataGrid>
<syncfusion:SfDataGrid x:Name="FirstLevelNestedGrid" HeaderRowHeight="0" />
</syncfusion:GridViewDefinition.DataGrid>
</syncfusion:GridViewDefinition>
</syncfusion:SfDataGrid.DetailsViewDefinition>
</ syncfusion:SfDataGrid>
Freeze panes
WPF 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 |
---|---|
Set the frozen rows count at top of the SfDataGrid. | |
Set the footer rows count at </kbd>bottom</kbd> of the SfDataGrid. | |
Set the frozen columns count in left side of the SfDataGrid. | |
Set the frozen columns in right side of the SfDataGrid. |
<syncfusion:SfDataGrid x:Name="dataGrid"
FooterColumnCount="1"
FooterRowsCount="3"
FrozenColumnCount="1"
FrozenRowsCount="2"
ItemsSource="{Binding Orders}">
dataGrid.FooterColumnCount = 1;
dataGrid.FrozenColumnCount = 1;
dataGrid.FrozenRowsCount = 2;
dataGrid.FrozenRowsCount = 3;
Differentiate frozen rows from normal rows
You can differentiate the frozen rows and footer rows from normal rows by writing style for VirtualizingCellsControl and by customizing the FrozenRow
and FooterRow
visual states.
<Style TargetType="{x:Type syncfusion:VirtualizingCellsControl}">
<Setter Property="Background" Value="Transparent">
<Setter Property="BorderBrush" Value="Gray">
<Setter Property="BorderThickness" Value="0">
<Setter Property="IsTabStop" Value="False">
<Setter Property="FocusVisualStyle" Value="{x:Null}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type syncfusion:VirtualizingCellsControl}">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="BorderStates">
<VisualState x:Name="NormalRow">
<VisualState x:Name="FrozenRow">
<Storyboard BeginTime="0">
<ThicknessAnimationUsingKeyFrames BeginTime="0"
Duration="1"
Storyboard.TargetName="PART_RowBorder"
Storyboard.TargetProperty="BorderThickness">
<!-- Border Thickness for Frozen rows -->
<EasingThicknessKeyFrame KeyTime="0" Value="0, 0, 0, 3"/>
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="FooterRow">
<Storyboard BeginTime="0">
<ThicknessAnimationUsingKeyFrames BeginTime="0"
Duration="1"
Storyboard.TargetName="PART_RowBorder"
Storyboard.TargetProperty="BorderThickness">
<!-- Border Thickness for Footer rows -->
<EasingThicknessKeyFrame KeyTime="0" Value="0, 3, 0, 0" />
</ThicknessAnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames BeginTime="0"
Duration="1"
Storyboard.TargetName="PART_RowBorder"
Storyboard.TargetProperty="Margin">
<EasingThicknessKeyFrame KeyTime="0" Value="0, -1, 0, 0" />
</ThicknessAnimationUsingKeyFrames>
</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="2,2"
StrokeThickness="1"
Visibility="{TemplateBinding CurrentFocusRowVisibility}" />
<Rectangle Clip="{TemplateBinding RowBackgroundClip}" Fill="{TemplateBinding Background}" />
<Border Background="{TemplateBinding RowSelectionBrush}"
Clip="{TemplateBinding SelectionBorderClipRect}"
Visibility="{TemplateBinding SelectionBorderVisiblity}" />
<Border Background="{TemplateBinding RowHoverBackgroundBrush}"
BorderBrush="{TemplateBinding RowHoverBackgroundBrush}"
BorderThickness="{TemplateBinding RowHighlightBorderThickness}"
Clip="{TemplateBinding HighlightBorderClipRect}"
SnapsToDevicePixels="True"
Visibility="{TemplateBinding HighlightSelectionBorderVisiblity}" />
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter />
<Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
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 QueryColumnDragging 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.dataGrid.QueryColumnDragging +=dataGrid_QueryColumnDragging;
void dataGrid_QueryColumnDragging(object sender, QueryColumnDraggingEventArgs e)
{
if (e.Reason == QueryColumnDraggingReason.Dropping)
{
//used to get frozen column index from the frozen column count
var frozenColIndex = dataGrid.FrozenColumnCount +
this.dataGrid.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
-
When using
DetailsView
with freeze panes, exception will be raised like DetailsView is not supported with Freeze panes support. -
When
AllowFrozenGroupHeaders
is true, frozen rows will not be considered. -
SfDataGrid has support to freeze the number of rows from top or bottom. There is no support to freeze a specific row.
NOTE
- Header rows, table summary rows and row header are frozen regardless of
FrozenRowsCount
andFooterRowsCount
.
FrozenRowsCount
andFooterRowsCount
values should be less than the number of rows and column visible.