Selection in WinUI TreeGrid
18 Apr 202224 minutes to read
SfTreeGrid allows you to select one or more rows.
Current cell navigation
Keyboard navigation through the rows is determined based on the NavigationMode property. NavigationMode.Cell allows you navigate between the cells in a row and navigate between rows. NavigationMode.Row allows you navigate only between rows.
Selection modes
The SelectionMode property defines the behavior of selection in tree grid. If SelectionMode
is Single, you can select a single row, and if the SelectionMode
is Extended or Multiple, you can select multiple rows. If you want to disable the selection, set SelectionMode
to None.
<treeGrid:SfTreeGrid Name="sfTreeGrid"
AutoExpandMode="RootNodesExpanded"
AutoGenerateColumns="False"
NavigationMode="Row"
SelectionMode="Single"
ColumnSizer="Star"
ExpanderColumn="FirstName"
ItemsSource="{Binding Employees}"
ParentPropertyName="ID"
ChildPropertyName="ReportsTo"
SelfRelationRootValue="-1" />
Disable selection for rows and columns
You can disable selection and navigation on particular column by setting the GridColumn.AllowFocus property. You can disable selection on particular row or column by handling the CurrentCellActivating event.
Multiple row selection
The tree grid allows you select multiple rows by setting the SelectionMode
property to Extended
or Multiple
, where you can select multiple rows by mouse click and also using the key modifiers.
When using Extended
, you can select multiple rows by pressing the key modifiers Ctrl
and Shift
.
<treeGrid:SfTreeGrid Name="sfTreeGrid"
AutoExpandMode="RootNodesExpanded"
AutoGenerateColumns="False"
NavigationMode="Row"
SelectionMode="Extended"
ColumnSizer="Star"
ExpanderColumn="FirstName"
ItemsSource="{Binding PersonDetails}"
ParentPropertyName="ID"
ChildPropertyName="ReportsTo"
SelfRelationRootValue="-1" />
NOTE
When
SelectionMode
isMultiple
, you can select or deselect multiple rows by clicking the respective row. In multiple selection, pressing the navigation keys moves only the current cell, and you can select or deselect by pressing theSpace
key.
Get selected rows
The SelectedItem property returns the data object of the selected row, and the SelectedIndex property returns the index of the SelectedItem
in tree grid. The SelectedItem
denotes the first selected row in multiple selection.
The CurrentItem returns the data object that currently has focus, and the CurrentColumn denotes the TreeGridColumn that currently has focus.
Row selection
You can get all the selected records using the SelectedItems property, and you can also get all the selected rows information using SfTreeGrid.SelectionController.SelectedRows, which is a collection of TreeGridRowInfo.
CurrentItem vs SelectedItem
Both SelectedItem and CurrentItem
return the same data object when a single row is selected in tree grid. When you select more than one rows or cells, the record that had been selected initially is maintained in SelectedItem
, and the record that currently has focus is maintained in CurrentItem
.
Programmatic selection
Process selection using properties
You can select a single row by setting the SelectedItem
property or SelectedIndex property.
var recordIndex = this.sfTreeGrid.ResolveToNodeIndex(6);
this.sfTreeGrid.SelectedIndex = recordIndex;
var node = this.sfTreeGrid.GetNodeAtRowIndex(6);
this.sfTreeGrid.SelectedItem = node.Item;
In row selection, you can select multiple rows by adding data objects to the SelectedItems
property.
var viewModel = this.sfTreeGrid.DataContext as ViewModel;
foreach (var order in viewModel.PersonDetails)
{
if (order.LastName == "Joseph")
this.sfTreeGrid.SelectedItems.Add(order);
}
Process selection using methods
You can select a range of rows using the SelectRows method in row selection.
this.sfTreeGrid.SelectRows(3, 7);
Process current cell
When you set CurrentItem to a particular record, the CurrentCell will be moved to the corresponding record. When SelectionMode
is Multiple
or Extended
, the selection will added to a particular record item. When SelectionMode
is Single
, the selection will added to a single cell.
You can move the CurrentCell
to a particular rowColumnIndex using the MoveCurrentCell method.
this.sfTreeGrid.SelectionController.MoveCurrentCell(new RowColumnIndex(3, 2), false);
Clear selection
You can clear the selection using the ClearSelections method. In row selection, you can remove the selection by setting null to the SelectedItem
or clearing the SelectedItems
property.
this.sfTreeGrid.SelectionController.ClearSelections(true);
Scrolling rows and columns
Automatic scrolling on drag selection
SfTreeGrid scrolls rows and columns automatically when you try to perform the drag selection like in Excel. You can enable or disable AutoScrolling by setting the AutoScroller.AutoScrolling property.
this.sfTreeGrid.AutoScroller.AutoScrolling = AutoScrollOrientation.Both;
Scroll to a particular row or column index
You can scroll programmatically to particular cell using the ScrollInView method by passing row and column index.
this.sfTreeGrid.ScrollInView(new RowColumnIndex(10, 5));
Scroll to selected item
You can scroll programmatically to the SelectedItem
using the ScrollInView
method.
var rowIndex = this.sfTreeGrid.ResolveToRowIndex(this.sfTreeGrid.SelectedItem);
var columnIndex = this.sfTreeGrid.ResolveToStartColumnIndex();
this.sfTreeGrid.ScrollInView(new RowColumnIndex(rowIndex, columnIndex));
Mouse and keyboard behaviors
Keyboard behavior
Key or Key combinations |
Description |
DownArrow | Moves CurrentCell directly below the active current cell. If the CurrentCell is in the last row, pressing the DownArrow does nothing. |
UpArrow | Moves the CurrentCell directly above the active current cell. If the CurrentCell is in the first row, pressing the UpArrow does nothing. |
LeftArrow | Moves the current cell to previous to the active current cell. If the CurrentCell is in the first cell, pressing the LeftArrow does nothing. If the focused row is group header, the group will be collapsed when it is in expanded state. |
RightArrow | Moves the current cell to next to the active current cell. If the CurrentCell is in the last cell, pressing the RightArrow does nothing. If the focused row is group header, the group will be expanded when it is in collapsed state. |
Home / Ctrl + LeftArrow | Moves the current cell to the first cell of the current row. |
End / Ctrl + RightArrow | Moves the current cell to the last cell of the current row. |
PageDown | The tree grid will be scrolled to the next set of rows that is not displayed in view, including the row that is partially displayed, and the current cell is set to the last row. |
PageUp | The tree grid will be scrolled to the previous set of rows that is not displayed in view, including the row that is partially displayed, and the current cell is set to the first row. |
Tab | Moves the current cell to next to the active current cell. If the active current cell is the last cell of the current row, the focus will be moved to the first cell of the row next to the current row. If the active current cell is the last cell of the last row, the focus will be moved to next control in the tab order of the parent container. |
Shift + Tab | Moves the current cell to previous cell to the active current cell. If the active current cell is the first cell of the current row, the current cell will be moved to the last cell of the row previous to the current row. If the active current cell is the first cell of the first row, the focus will be moved to the previous control in the tab order of the parent container. |
Ctrl + DownArrow | Moves the current cell to the current column of the last row. |
Ctrl + UpArrow | Moves the current cell to the current column of the first row. |
Ctrl + Home | Moves the current cell to the first cell of the first row. |
Ctrl + End | Moves the current cell to the last cell of the last row. |
Enter | If the active current cell is in edit mode, the changes will be committed, and moves the current cell to below the active current cell. If the active current cell is in the last row, commits changes only and retains the same cell. |
Ctrl + Enter | Commits only the changes when the current cell is in edit mode and retains the focus in same cell. |
F2 | If the property is true, and the property is true for the current column, the current cell enters into edit mode. |
Esc | If the current cell is in edit mode, reverts the changes that had been done in the current cell. If the underlying source implements , clicking the Esc key for the second time cancels the edit mode for entire row. |
Ctrl + A | All rows or cells will be selected. |
Shift key combinations
When SelectionMode
is set to Extended
, you can select multiple rows using the navigation keys along with the Shift key. Before starting navigation, the current cell will be marked as a pressed cell, and the selection will be done in all rows between the pressed cell and current cell.
Key combinations |
Shift + DownArrow |
Shift + UpArrow |
Shift + LeftArrow |
Shift + Home |
Shift + End |
Shift + PageDown |
Shift + PageUp |
Shift + Ctrl + DownArrow |
Shift + Ctrl + UpArrow |
Shift + Ctrl + RightArrow |
Shift + Ctrl + LeftArrow |
Shift + Ctrl + Home |
Shift + Ctrl + End |
Shift + Ctrl + PageDown |
Shift + Ctrl + PageUp |
Mouse behavior
You can enable or disable the selection when the mouse button is in the pressed state by setting the AllowSelectionOnPointerPressed property.
When SelectionMode
is set to Extended
, you can select multiple rows by clicking any cell along with Ctrl
and Shift
keys. When you click a cell along with Ctrl
key, you can select or deselect a particular row. When you click a cell along with Shift
key, you can select the range rows from the pressed cell to the current cell.
Customize mouse and keyboard behaviors
You can customize the mouse and keyboard behaviors by overriding the selection controller. Refer to the Customizing Selection Behaviors section to learn about override the selection controller.
Events
CurrentCellActivating
The CurrentCellActivating event will occurs before moving the current cell to particular cell. CurrentCellActivatingEventArgs has following members which provides information for CurrentCellActivating
event.
-
ActivationTrigger - Returns the reason for moving the current cell.
-
CurrentRowColumnIndex - RowColumnIndex of the cell where the current cell need to move.
-
PreviousRowColumnIndex -
RowColumnIndex
of the cell from where the current cell moved.
<treeGrid:SfTreeGrid Name="sfTreeGrid"
AutoExpandMode="RootNodesExpanded"
AutoGenerateColumns="False"
ColumnSizer="Star"
ExpanderColumn="FirstName"
CurrentCellActivating="sfTreeGrid_CurrentCellActivating"
ItemsSource="{Binding Employees}"
ParentPropertyName="ID"
ChildPropertyName="ReportsTo"
SelfRelationRootValue="-1"
LiveNodeUpdateMode="AllowDataShaping" />
this.sfTreeGrid.CurrentCellActivating += sfTreeGrid_CurrentCellActivating;
private void sfTreeGrid_CurrentCellActivating(object sender, Syncfusion.UI.Xaml.DataGrid.CurrentCellActivatingEventArgs e)
{
}
You can cancel the current cell moving process within this event by setting GridCurrentCellActivatingEventArgs.Cancel to true.
private void sfTreeGrid_CurrentCellActivating(object sender, Syncfusion.UI.Xaml.DataGrid.CurrentCellActivatingEventArgs e)
{
var provider = this.sfTreeGrid.View.GetPropertyAccessProvider();
var record = this.sfTreeGrid.GetNodeAtRowIndex(e.CurrentRowColumnIndex.RowIndex).Item;
if (record == null)
return;
var column = this.sfTreeGrid.Columns[this.sfTreeGrid.ResolveToGridVisibleColumnIndex(e.CurrentRowColumnIndex.ColumnIndex)];
var cellValue = provider.GetValue(record, column.MappingName);
if (cellValue.ToString() == "1001")
e.Cancel = true;
}
CurrentCellActivated
The CurrentCellActivated event occurs after the current cell moves to the corresponding cell. CurrentCellActivatedEventArgs has the following members, which provide information to the CurrentCellActivated
event:
-
ActivationTrigger - Returns the reason of the current cell movement.
-
CurrentRowColumnIndex -
RowColumnIndex
of the cell where the current cell move. -
PreviousRowColumnIndex -
RowColumnIndex
of the cell where the current cell moved.
<treeGrid:SfTreeGrid Name="sfTreeGrid"
AutoExpandMode="RootNodesExpanded"
AutoGenerateColumns="False"
ColumnSizer="Star"
ExpanderColumn="FirstName"
CurrentCellActivated="sfTreeGrid_CurrentCellActivated"
ItemsSource="{Binding Employees}"
ParentPropertyName="ID"
ChildPropertyName="ReportsTo"
SelfRelationRootValue="-1"
LiveNodeUpdateMode="AllowDataShaping" />
this.sfTreeGrid.CurrentCellActivated += sfTreeGrid_CurrentCellActivated;
private void sfTreeGrid_CurrentCellActivated(object sender, Syncfusion.UI.Xaml.DataGrid.CurrentCellActivatedEventArgs e)
{
}
SelectionChanging
The SelectionChanging event occurs before processing the selection to a particular row or cell. This event is triggered only to the keyboard and mouse interactions. GridSelectionChangingEventArgs has the following members, which provide information to the SelectionChanging
event.
-
AddedItems - Collection of GridRowInfo where the selection is going to be processed.
-
RemovedItems - Collection of
GridRowInfo
where the selection is going to be removed.
<treeGrid:SfTreeGrid Name="sfTreeGrid"
AutoExpandMode="RootNodesExpanded"
AutoGenerateColumns="False"
ColumnSizer="Star"
ExpanderColumn="FirstName"
SelectionChanging="sfTreeGrid_SelectionChanging"
ItemsSource="{Binding Employees}"
ParentPropertyName="ID"
ChildPropertyName="ReportsTo"
SelfRelationRootValue="-1"
LiveNodeUpdateMode="AllowDataShaping" />
this.sfTreeGrid.SelectionChanging += sfTreeGrid_SelectionChanging;
private void sfTreeGrid_SelectionChanging(object sender, Syncfusion.UI.Xaml.Grids.GridSelectionChangingEventArgs e)
{
}
SelectionChanged
The SelectionChanged event occurs after the selection process is completed for a particular row or cell in tree grid. GridSelectionChangedEventArgs has the following members, which provide information to the SelectionChanged event:
-
AddedItems - Collection of
GridRowInfo
where the selection has been processed. -
RemovedItems - Collection of
GridRowInfo
where the selection has been removed.
<treeGrid:SfTreeGrid Name="sfTreeGrid"
AutoExpandMode="RootNodesExpanded"
AutoGenerateColumns="False"
ColumnSizer="Star"
ExpanderColumn="FirstName"
SelectionChanged="sfTreeGrid_SelectionChanged"
ItemsSource="{Binding Employees}"
ParentPropertyName="ID"
ChildPropertyName="ReportsTo"
SelfRelationRootValue="-1"
LiveNodeUpdateMode="AllowDataShaping" />
this.sfTreeGrid.SelectionChanged += sfTreeGrid_SelectionChanged;
private void sfTreeGrid_SelectionChanged(object sender, Syncfusion.UI.Xaml.Grids.GridSelectionChangedEventArgs e)
{
}
Appearance
Change selection background and foreground
You can change the selection background and foreground using the SelectionBackGround and SelectionForeGround properties.
<treeGrid:SfTreeGrid Name="sfTreeGrid"
AutoExpandMode="RootNodesExpanded"
AutoGenerateColumns="False"
SelectionMode="Multiple"
ColumnSizer="Star"
ExpanderColumn="FirstName"
ItemsSource="{Binding Employees}"
ParentPropertyName="ID"
ChildPropertyName="ReportsTo"
SelfRelationRootValue="-1"
SelectionBackground="SkyBlue"
SelectionForeground="DarkBlue" />
Change current cell border style
You can change the current cell border thickness and border color using the CurrentCellBorderThickness and CurrentCellBorderBrush properties.
<treeGrid:SfTreeGrid Name="sfTreeGrid"
AutoExpandMode="RootNodesExpanded"
AutoGenerateColumns="False"
SelectionMode="Multiple"
ColumnSizer="Star"
ExpanderColumn="FirstName"
ItemsSource="{Binding Employees}"
ParentPropertyName="ID"
ChildPropertyName="ReportsTo"
SelfRelationRootValue="-1"
LiveNodeUpdateMode="AllowDataShaping"
CurrentCellBorderBrush="Red"
CurrentCellBorderThickness="1.6" />
Customize row selection border
You can customize the row selection by editing the control template of TreeGridRowControl.
<Application.Resources>
<Style TargetType="treeGrid:TreeGridRowControl">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="#33000000" />
<Setter Property="Foreground" Value="#FF000000"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="treeGrid:TreeGridRowControl">
<Grid BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected" />
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter Target="PART_SelectionBorder.Visibility" Value="Visible" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="SelectedPointerOver">
<VisualState.Setters>
<Setter Target="PART_SelectionBorder.Visibility" Value="Visible" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="SelectedPressed">
<VisualState.Setters>
<Setter Target="PART_SelectionBorder.Visibility" Value="Visible" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="UnselectedPointerOver" />
<VisualState x:Name="UnselectedPressed" />
<VisualState x:Name="Focused">
<VisualState.Setters>
<Setter Target="PART_FocusRect.Visibility" Value="Visible" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="PART_BackgroundBorder"
Margin="{TemplateBinding IndentMargin}"
Background="Transparent"
Visibility="Visible">
<Rectangle x:Name="PART_FocusRect"
Margin="1,2,2,2"
Fill="Transparent"
Stroke="DarkGray"
StrokeDashArray="2,2"
StrokeThickness="1"
Visibility="Collapsed" />
</Border>
<!--Adding new border to show border for whole selected row-->
<Border x:Name="PART_SelectionBorder"
Margin="{TemplateBinding IndentMargin}"
Background="{TemplateBinding SelectionBackground}"
Visibility="Collapsed"
BorderBrush="Red"
BorderThickness="1.5,1.5,1.5,2.5"
Opacity="0.75"/>
<ContentPresenter />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
Customize selection behaviors
The tree grid processes the selection operations in selection controller. TreeGridRowSelectionController processes selection operations when selection unit is row.
You can customize the default row selection behaviors by overriding the TreeGridRowSelectionController
class and set it to SfTreeGrid.SelectionController.
this.sfTreeGrid.SelectionController = new GridSelectionControllerExt(this.sfTreeGrid);
public class GridSelectionControllerExt : TreeGridRowSelectionController
{
public GridSelectionControllerExt(SfTreeGrid treeGrid) : base(treeGrid)
{
}
}
Scroll and select the record programmatically
You can scroll to the record programmatically using the ScrollInView method by passing the row index of the record. You can get the row index of the record using the ResolveToRowIndex extension method present in Syncfusion.UI.Xaml.TreeGrid.Helpers
.
You can select the record programmatically by setting the SelectedItem
property in tree grid.
private void sfTreegrid_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
var selectedItem = (this.sfTreeGrid.DataContext as ViewModel).SelectedItem;
var rowindex = this.sfTreeGrid.ResolveToRowIndex(selectedItem);
var columnindex = this.sfTreeGrid.ResolveToStartColumnIndex();
//Make the row in to available on the view.
this.sfTreeGrid.ScrollInView(new RowColumnIndex(rowindex, columnindex));
//Set the SelectedItem in SfTreeGrid.
this.sfTreeGrid.SelectedItem = selectedItem;
}
Prevent the selection when right-click
You can prevent the selection when right-clicking in tree grid by customizing the TreeGridRowSelectionController
and overriding the ProcessPointerPressed.
protected override void ProcessPointerPressed(PointerRoutedEventArgs args, RowColumnIndex rowColumnIndex)
{
var properties = args.GetCurrentPoint(TreeGrid).Properties;
if (properties.IsRightButtonPressed)
{
args.Handled = false;
}
else
base.ProcessPointerPressed(args, rowColumnIndex);
}
Select the rows based on cell value
In tree grid, you can select the rows based on cell value by adding the corresponding records to SelectedItems
. You can get the cell value of a particular cell using the View.GetPropertyAccessProvider method.
private void Button_Click(object sender, RoutedEventArgs e)
{
var reflector = sfTreeGrid.View.GetPropertyAccessProvider();
var totalRowIndex = sfTreeGrid.View.Nodes.Count;
var totalColumnIndex = sfTreeGrid.Columns.Count;
for (int recordIndex = 0; recordIndex < totalRowIndex; recordIndex++)
{
for (int colindex = 0; colindex < totalColumnIndex; colindex++)
{
var record = this.sfTreeGrid.View.Nodes[recordIndex];
var mappingName = sfTreeGrid.Columns[colindex].MappingName;
//Get the cell value based on mappingName.
var currentCellValue = reflector.GetValue(record.Item, mappingName);
if (currentCellValue == "Steven")
{
object node = sfTreeGrid.View.Nodes[recordIndex];
//selected rows should be added here.
sfTreeGrid.SelectedItems.Add((node as TreeNode).Item);
}
}
}
}
Search and select the record
You can search and select a record in tree grid based on the searched text using the TextChanged event of TextBox.
private void TextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
var textBox = sender as TextBox;
var treeGrid = this.sfTreeGrid;
if (textBox.Text == "")
treeGrid.SelectedItems.Clear();
for (int i = 0; i < treeGrid.View.Nodes.Count; i++)
{
if (Provider == null)
Provider = treeGrid.View.GetPropertyAccessProvider();
if (treeGrid.View.Nodes[i].HasChildNodes && treeGrid.View.Nodes[i].ChildNodes.Count == 0)
{
treeGrid.ExpandNode(treeGrid.View.Nodes[i]);
treeGrid.CollapseNode(treeGrid.View.Nodes[i]);
}
else if (treeGrid.View.Nodes[i].HasChildNodes)
{
dataRow = (treeGrid.View.Nodes[i].Item as EmployeeInfo);
FindMatchText(dataRow);
GetChildNodes(treeGrid.View.Nodes[i]);
}
else
{
dataRow=(treeGrid.View.Nodes[i].Item as EmployeeInfo);
FindMatchText(dataRow);
}
}
}
NOTE
View sample in GitHub
Read cell values from selected items
You can get the cell values of SelectedItems
using SfTreeGrid.SelectedItems
and internal reflector, which reflects the field value from data object based on field name.
private void Button_Click(object sender, RoutedEventArgs e)
{
listBox.Items.Clear();
// Get the selected items of SfTreeGrid
var reflector = this.sfTreeGrid.View.GetPropertyAccessProvider();
foreach (var row in this.sfTreeGrid.SelectedItems)
{
foreach (var column in sfTreeGrid.Columns)
{
//Get the value from data object based on MappingName
var cellvalue = reflector.GetValue(row, column.MappingName);
//Returns the display value of the cell from data object based on MappingName
listBox.Items.Add(cellvalue.ToString());
}
}
}
Show the selection of row/cell when setting the background
The Row
/Cell
selection border is behind the grid cell content. So, when you apply the background for a row, the selection is not displayed in UI
. You can overcome this by setting opacity in TreeGridCell.
<Application.Resources>
<Style TargetType="treeGrid:TreeGridCell">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="Blue" Opacity="0.5"/>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
Set the current cell on a particular row when tree grid is loaded
You can set the current cell in tree grid using the treeGrid.SelectionController.MoveCurrentCell method.
private void sfTreeGrid_Loaded(object sender, RoutedEventArgs e)
{
var viewModel = this.sfTreeGrid.DataContext as ViewModel;
//find the RowIndex for particular record
var RowIndex = this.sfTreeGrid.ResolveToRowIndex(viewModel.EmployeeInfo[2]);
// find the ColumnIndex for that row.
var ColumnIndex = this.sfTreeGrid.ResolveToScrollColumnIndex(1);
// CurrentCell is set if MappingName is EmployeeID
if (this.sfTreeGrid.Columns[ColumnIndex].MappingName == "EmployeeID")
this.sfTreeGrid.SelectionController.MoveCurrentCell(new RowColumnIndex(RowIndex, ColumnIndex));
}