Selection in WPF DataGrid (SfDataGrid)
16 Oct 202324 minutes to read
WPF DataGrid (SfDataGrid) allows you to select one or more rows or cells. For selecting specific row or group of rows you have to set SelectionUnit as Row and for selecting a specific cell or group of cells you have to set SelectionUnit
as Cell or Any. In SelectionUnit.Any option you can select the row by clicking on row header.
Current Cell Navigation
Keyboard navigation through the cells and rows is determined based on the NavigationMode property. NavigationMode.Cell allows you to navigate between the cells in a row as well as between rows. NavigationMode.Row allows you to navigate only between rows. It is not possible to set NavigationMode.Row
when cell selection is enabled (SelectionUnit
is Cell or Any).
Selection Modes
The SelectionUnit
and SelectionMode properties together define the behavior of selection in SfDataGrid. If the SelectionMode
is Single, you can able to select single row or cell, and if the SelectionMode
is Extended
or Multiple
, you can able to select multiple rows or cell, and if you want to disable the selection you need to set SelectionMode
as None
,
<Syncfusion:SfDataGrid x:Name=”dataGrid”
SelectionUnit="Row"
NavigationMode="Cell"
SelectionMode="Single"
ItemsSource="{Binding Orders}">
Disable selection for rows and columns
You can disable selection and navigation on particular column by setting GridColumn.AllowFocus property. You can disable selection on particular row or cell or column by handling CurrentCellActivating event.
NOTE
It is not possible to select header rows, table summary rows, unbound rows which are above the table summary row when it’s placed in top and the unbound rows which are below table summary rows when it’s placed in bottom of SfDataGrid.
Multiple Row or Cell Selection
The WPF DataGrid (SfDataGrid) allows you to select multiple rows or cells by setting SelectionMode property as Extended or Multiple, where you can select multiple rows or cells by dragging the mouse on SfDataGrid and also using the key modifiers.
While using Extended
, you can select multiple rows or cells by pressing the key modifiers Ctrl and Shift.
<syncfusion:SfDataGrid x:Name="dataGrid"
SelectionUnit="Cell"
NavigationMode="Cell"
SelectionMode="Extended"
ItemsSource="{Binding Orders}">
NOTE
When the SelectionMode as Multiple, you can select or deselect multiple rows and cells by clicking the respective cell or row. Also in multiple selection pressing navigation keys will move only the current cell and you can select or deselect by pressing space key.
<syncfusion:SfDataGrid x:Name="dataGrid"
SelectionUnit="Cell"
NavigationMode="Cell"
SelectionMode="Multiple"
ItemsSource="{Binding Orders}">
CheckBox column selection
SfDataGrid
allows you to select or deselect rows by interacting with the check box in a column. All the rows in a datagrid can be selected by interacting with an intuitive check box in the column header. Refer to GridCheckBoxSelectorColumn documentation for more information.
Get Selected Rows and Cells
The SelectedItem property returns the data object of the selected row and the SelectedIndex property returns the index of the SelectedItem
in SfDataGrid. SelectedItem
denotes the first selected row in multiple selection.
The CurrentItem returns the data object that currently has the focus and the CurrentColumn denotes the GridColumn that currently has the focus. The CurrentCellInfo returns an instance GridCellInfo which contains the information about the cell that currently has the focus.
Row Selection
You can gets all the selected records through SelectedItems property and you can also get all selected rows information through SfDataGrid.SelectionController.SelectedRows which is the collection of GridRowInfo.
Cell Selection
You can get all selected cells information through SfDataGrid.SelectionController.SelectedCells property which is the collection of GridSelectedCellsInfo.
You can get the selected cells as GridCellInfo collection by using GetSelectedCells method.
List<GridCellInfo> selectedCells = this.dataGrid.GetSelectedCells();
CurrentItem vs SelectedItem
Both SelectedItem and CurrentItem returns the same data object when there is single cell or row is selected in SfDataGrid. When you have selected more than one rows or cells, the record that had been selected initially is maintained in SelectedItem
and the record that currently have focus is maintained in CurrentItem
.
Programmatic selection
Process selection using properties
You can select a single row or cell by setting SelectedItem property or SelectedIndex property.
var recordIndex = this.dataGrid.ResolveToRecordIndex(5);
this.dataGrid.SelectedIndex = recordIndex;
var record = this.dataGrid.GetRecordAtRowIndex(6);
this.dataGrid.SelectedItem = record;
In Row selection, you can select multiple rows by adding data objects to SelectedItems property.
var viewModel = this.dataGrid.DataContext as ViewModel;
foreach(var order in viewModel.Orders)
{
if (order.Country == "Mexico")
this.dataGrid.SelectedItems.Add(order);
}
Process selection using methods
You can select range of rows through SelectRows method in row selection.
this.dataGrid.SelectRows(3, 7);
You can select a specific cell by using the SelectCell method in cell selection.
var record = this.dataGrid.GetRecordAtRowIndex(3);
var column = this.dataGrid.Columns[1];
this.dataGrid.SelectCell(record, column);
You can select a range of cells through SelectCells method in cell selection.
public MainWindow()
{
InitializeComponent();
this.dataGrid.Loaded += dataGrid_Loaded;
this.dataGrid.SelectionController = new GridSelectionControllerExt(this.dataGrid);
}
private void dataGrid_Loaded(object sender, RoutedEventArgs e)
{
var firstRecord = this.dataGrid.GetRecordAtRowIndex(3);
var lastRecord = this.dataGrid.GetRecordAtRowIndex(7);
var firstColumn = this.dataGrid.Columns[1];
var lastColumn = this.dataGrid.Columns[3];
this.dataGrid.SelectCells(firstRecord, firstColumn, lastRecord, lastColumn);
(this.dataGrid.SelectionController as GridSelectionControllerExt).rowColumnIndex = new RowColumnIndex(7, 3);
//Updates the PressedRowColumnIndex value in the GridBaseSelectionController.
(this.dataGrid.SelectionController as GridSelectionControllerExt).UpdatePressedIndex();
}
public class GridSelectionControllerExt : GridCellSelectionController
{
//Overrides the GridCellSelectionController class to update the PressedRowColumnIndex.
public GridSelectionControllerExt(SfDataGrid datagrid)
: base(datagrid)
{
}
private RowColumnIndex rowColumnIndex;
public RowColumnIndex RowColumnIndex
{
get { return rowColumnIndex; }
set { rowColumnIndex = value; }
}
//Updates the PressedRowColumnIndex to maintain the ShiftSelection.
public void UpdatePressedIndex()
{
this.isInShiftSelection = true;
this.PressedRowColumnIndex = RowColumnIndex;
}
}
You can select all the rows or cells using SelectAll method.
this.dataGrid.SelectAll();
Process Current Cell
When you set the CurrentItem to particular record, the CurrentCell will be moved to corresponding record when the SelectionMode is Multiple or Extended and the selection will added to the particular record item when the SelectionMode
is Single.
var viewModel = this.dataGrid.DataContext as ViewModel;
this.dataGrid.CurrentItem = viewModel.Orders.FirstOrDefault(order => order.Country == "Spain");
You can move the CurrentCell to a particular rowColumnIndex by using the MoveCurrentCell method.
this.dataGrid.MoveCurrentCell(new RowColumnIndex(3,2), false);
Clear Selection
You can clear the selection by using the ClearSelection method. In Row Selection you can also remove the selection by setting null to SelectedItem or clearing the SelectedItems property.
this.dataGrid.SelectionController.ClearSelections(true);
You can clear selection on group of cells by using the UnSelectCells method in cell selection.
var firstRecord = this.dataGrid.GetRecordAtRowIndex(3);
var lastRecord = this.dataGrid.GetRecordAtRowIndex(7);
var firstColumn = this.dataGrid.Columns[1];
var lastColumn = this.dataGrid.Columns[3];
this.dataGrid.UnSelectCells(firstRecord, firstColumn, lastRecord, lastColumn);
You can clear the selection on particular cell by using the UnSelectCell method in cell selection.
var removeRecord = this.dataGrid.GetRecordAtRowIndex(5);
var removeColumn = this.dataGrid.Columns[2];
this.dataGrid.UnSelectCell(removeRecord, removeColumn);
Selection in Master-Details View
Master-Details View provides support to select one or more rows or cells in DetailsViewDataGrid. You can’t able to maintain the selection in both ParentDataGrid and DetailsViewDataGrid
. Selection will be maintained either in ParentDataGrid or in DetailsViewDataGrid
.
Getting SelectedDetailsViewDataGrid
You can get the currently selected DetailsViewDataGrid by using the SelectedDetailsViewGrid property of parent DataGrid.
var detailsViewDataGrid = this.dataGrid.SelectedDetailsViewGrid;
For accessing nested level SelectedDetailsViewGrid ,
var detailsViewDataGrid = this.dataGrid.SelectedDetailsViewGrid.SelectedDetailsViewGrid;
Getting SelectedItem from DetailsViewDataGrid
You can get the selected record of DetailsViewDataGrid by using the SelectedItem property.
var detailsViewDataGrid = this.datagrid.SelectedDetailsViewGrid;
var SelectedItem = detailsViewDataGrid.SelectedItem;
You can get the SelectedItem
while it’s changed using SelectionChanged event of ViewDefinition.DataGrid
.
<syncfusion:GridViewDefinition RelationalColumn="OrderDetails">
<syncfusion:GridViewDefinition.DataGrid>
<syncfusion:SfDataGrid x:Name="FirstDetailsViewGrid"
SelectionChanged="FirstDetailsViewGrid_SelectionChanged">
</syncfusion:SfDataGrid>
</syncfusion:GridViewDefinition.DataGrid>
</syncfusion:GridViewDefinition>
FirstDetailsViewGrid.SelectionChanged+=FirstDetailsViewGrid_SelectionChanged;
private void FirstDetailsViewGrid_SelectionChanged(object sender, Syncfusion.UI.Xaml.Grid.GridSelectionChangedEventArgs e)
{
var SelectedItem = (e.OriginalSender as DetailsViewDataGrid).SelectedItem;
}
NOTE
You can get the
SelectedIndex
andSelectedItems
also inSelectionChanged
event.
You can refer here to wire the events for ViewDefinition.DataGrid
based on AutoPopulateRelations
for different levels.
Get the CurrentItem of DetailsViewDataGrid
You can get the current record of the DetailsViewDataGrid by using the CurrentItem property.
var detailsViewDataGrid = this.datagrid.SelectedDetailsViewGrid;
var CurrentItem = detailsViewDataGrid.CurrentItem;
You can get the CurrentItem
while it’s changed using SelectionChanged event of ViewDefinition.DataGrid
.
<syncfusion:GridViewDefinition RelationalColumn="OrderDetails">
<syncfusion:GridViewDefinition.DataGrid>
<syncfusion:SfDataGrid x:Name="FirstDetailsViewGrid"
SelectionChanged="FirstDetailsViewGrid_SelectionChanged">
</syncfusion:SfDataGrid>
</syncfusion:GridViewDefinition.DataGrid>
</syncfusion:GridViewDefinition>
FirstDetailsViewGrid.SelectionChanged+=FirstDetailsViewGrid_SelectionChanged;
private void FirstDetailsViewGrid_SelectionChanged(object sender, Syncfusion.UI.Xaml.Grid.GridSelectionChangedEventArgs e)
{
var SelectedItem = (e.OriginalSender as DetailsViewDataGrid).CurrentItem;
}
You can refer here to wire the events from ViewDefinition.DataGrid
based on AutoPopulateRelations
for different levels.
Get CurrentCell of DetailsViewDataGrid
You can get the CurrentCell of DetailsViewDataGrid by using the SelectedDetailsViewGrid property. You can use different events of ViewDefinition.DataGrid
like CurrentCellBeginEdit, CurrentCellActivated to get the CurrentCell
.
var currentCell = this.dataGrid.SelectedDetailsViewGrid.SelectionController.CurrentCellManager.CurrentCell;
You can get the CurrentCell
using CurrentCellBeginEdit
event ViewDefinition.DataGrid
.
<syncfusion:GridViewDefinition RelationalColumn="OrderDetails">
<syncfusion:GridViewDefinition.DataGrid>
<syncfusion:SfDataGrid x:Name="FirstLevelNestedGrid"
CurrentCellBeginEdit=" FirstLevelNestedGrid_CurrentCellBeginEdit">
</syncfusion:SfDataGrid>
</syncfusion:GridViewDefinition.DataGrid>
</syncfusion:GridViewDefinition>
this.FirstLevelNestedGrid.CurrentCellBeginEdit += FirstLevelNestedGrid_CurrentCellBeginEdit;
void FirstLevelNestedGrid_CurrentCellBeginEdit(object sender, CurrentCellBeginEditEventArgs args)
{
var detailsViewDataGrid = args.OriginalSender as DetailsViewDataGrid;
var currentCell = detailsViewDataGrid.SelectionController.CurrentCellManager.CurrentCell;
}
You can refer here to wire the events from the ViewDefinition.DataGrid based on AutoPopulateRelations
for different levels.
Programmatic Selection in DetailsViewDataGrid
You can select data objects while loading DetailsViewDataGrid using DetailsViewLoading event.
<syncfusion:SfDataGrid Name="dataGrid"
DetailsViewLoading="dataGrid_DetailsViewLoading" >
</syncfusion:SfDataGrid>
this.dataGrid.DetailsViewLoading += dataGrid_DetailsViewLoading;
void dataGrid_DetailsViewLoading(object sender, DetailsViewLoadingAndUnloadingEventArgs e)
{
var record = e.DetailsViewDataGrid.GetRecordAtRowIndex(e.DetailsViewDataGrid.GetFirstDataRowIndex());
e.DetailsViewDataGrid.SelectedItem = record;
}
Getting the parent of DetailsViewDataGrid
You can get the immediate parent of DetailsViewDataGrid
through GetParentDataGrid helper method.
using Syncfusion.UI.Xaml.Grid.Helpers;
var parentDataGrid = this.dataGrid.SelectedDetailsViewGrid.GetParentDataGrid();
You can get the top level DataGrid for the DetailsViewDataGrid
through the GetTopLevelParentDataGrid helper method.
using Syncfusion.UI.Xaml.Grid.Helpers;
var dataGrid = this.detailsViewDataGrid.GetTopLevelParentDataGrid();
Getting the DetailsViewDataGrid based on index
You can get the DetailsViewDataGrid based on row index through GetDetailsViewGrid helper method.
var detailsViewDataGrid = this.dataGrid.GetDetailsViewGrid(2);
You can also get the DetailsViewDataGrid
based on the record index and relational column name using GetDetailsViewGrid
method.
var detailsViewDataGrid = this.dataGrid.GetDetailsViewGrid(0, "ProductDetails");
Programmatically expanding and scrolling DetailsViewDataGrid
You can expand the DetailsViewDataGrid
programmatically by calling ExpandDetailsViewAt
method by passing the record index.
int parentRowIndex = 2;
var recordIndex = this.dataGrid.ResolveToRecordIndex(parentRowIndex);
var record = this.dataGrid.View.Records[recordIndex];
if (!record.IsExpanded)
this.dataGrid.ExpandDetailsViewAt(recordIndex);
If the expanded DetailsViewDataGrid
is not in view, then you can scroll using DetailsViewManager.BringIntoView method.
int recordIndex = 20;
int index = 0;
int parentRowIndex = 25;
datagrid.ExpandDetailsViewAt(recordIndex);
foreach (var def in this.dataGrid.DetailsViewDefinition)
{
if (def.RelationalColumn == "ProductDetails")
{
index = this.dataGrid.DetailsViewDefinition.IndexOf(def);
index = parentRowIndex + index + 1;
}
}
//Get the Details view based upon the recordIndex and Column name
SfDataGrid detailsViewDataGrid = datagrid.GetDetailsViewGrid(recordIndex, "OrderDetails");
//Get the DetailsViewManager using Reflection
var propertyInfo = dataGrid.GetType().GetField("DetailsViewManager", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
DetailsViewManager detailsViewManager = propertyInfo.GetValue(dataGrid) as DetailsViewManager;
if (detailsViewDataGrid == null)
{
detailsViewManager.BringIntoView(index);
detailsViewDataGrid = this.dataGrid.GetDetailsViewGrid(this.dataGrid.ResolveToRecordIndex(recordIndex), " OrderDetails ");
}
You can get the sample from here.
Programmatically select the records in DetailsViewDataGrid which is not in view
Scrolling to the DetailsViewDataGrid
You can expand the DetailsViewDataGrid by using ExpandDetailsViewAt
helper method. If the DetailsViewDataGrid
is already expanded, you can use ScrollInView method to bring it into view. You can also use DetailsViewManager.BringIntoView method to get the DetailsViewDataGrid
into view.
//Find DetailsViewDataRow index based on relational column
int index = 0;
int parentRowIndex = 25;
foreach (var def in this.dataGrid.DetailsViewDefinition)
{
if (def.RelationalColumn == "ProductDetails")
{
index = this.dataGrid.DetailsViewDefinition.IndexOf(def);
index = parentRowIndex + index + 1;
}
}
//Get the DetailsViewManager using Reflection
var propertyInfo = dataGrid.GetType().GetField("DetailsViewManager", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
DetailsViewManager detailsViewManager = propertyInfo.GetValue(dataGrid) as DetailsViewManager;
var rowColumnIndex = new RowColumnIndex(index, 1);
//Get the DetailsViewDataGrid by passing the corresponding row index and relation name
var detailsViewDataGrid = this.dataGrid.GetDetailsViewGrid(this.dataGrid.ResolveToRecordIndex(parentRowIndex), "ProductDetails");
//If the DetailsViewDataGrid is not in view, then you can call the BringIntoView method.
if (detailsViewDataGrid == null)
{
detailsViewManager.BringIntoView(index);
detailsViewDataGrid = this.dataGrid.GetDetailsViewGrid(this.dataGrid.ResolveToRecordIndex(parentRowIndex), "ProductDetails");
}
else
{
//If the DetailsViewDataGrid is already expanded, bring that into view
dataGrid.ScrollInView(rowColumnIndex);
}
Select the record in the DetailsViewDataGrid
You can select the record of the DetailsViewDataGrid
programmatically at run time by setting the corresponding child grid record index to the SfDataGrid.SelectedIndex property.
detailsViewDataGrid.SelectedIndex = childIndex;
You can get the sample from here.
Customizing the SelectionController for DetailsViewDataGrid
The DetailsViewDataGrid process the selection operations in selection controller. Below are the built-in selection controllers,
-
GridSelectionController – Process selection operations when selection unit as row.
-
GridCellSelectionController – Process selection operations when selection unit as cell or Any.
You can customize the default row selection behavior by overriding GridSelectionController
class and set it to DetailsViewDataGrid.SelectionController
.
The below code-snippet explains you about the customization of GridSelectionController
class.
this.dataGrid.DetailsViewLoading += dataGrid_DetailsViewLoading;
void dataGrid_DetailsViewLoading(object sender, DetailsViewLoadingAndUnloadingEventArgs e)
{
if (!(e.DetailsViewDataGrid.SelectionController is GridSelectionControllerExt))
e.DetailsViewDataGrid.SelectionController = new GridSelectionControllerExt (e.DetailsViewDataGrid);
}
public class GridSelectionControllerExt : GridSelectionController
{
public GridSelectionControllerExt(SfDataGrid datagrid)
: base(datagrid)
{
}
}
Scrolling Rows or Columns
Automatic scrolling on Drag Selection
SfDataGrid will 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.dataGrid.AutoScroller.AutoScrolling = AutoScrollOrientation.Both;
Scroll to particular RowColumnIndex
You can scroll programmatically to particular cell using ScrollInView method by passing row and column index.
int rowIndex = this.dataGrid.GetLastDataRowIndex();
int columnIndex = this.dataGrid.GetLastColumnIndex();
this.dataGrid.ScrollInView(new RowColumnIndex(rowIndex, columnIndex));
Scroll to SelectedItem
You can scroll programmatically to the SelectedItem
using the ScrollInView
method.
using Syncfusion.UI.Xaml.Grid.Helpers;
var rowIndex = this.datagrid.ResolveToRowIndex(this.datagrid.SelectedItem);
var columnIndex = this.datagrid.ResolveToStartColumnIndex();
this.datagrid.ScrollInView(new RowColumnIndex(rowIndex, columnIndex));
Mouse and Keyboard Behaviors
Keyboard Behavior
Key or KeyCombinations | Description |
---|---|
DownArrow | Moves CurrentCell directly below the active current cell. If the CurrentCell is in last row, pressing DownArrow does nothing. |
UpArrow | Moves the CurrentCell directly above the active current cell. If the CurrentCell is in first row, pressing UpArrow does nothing. |
LeftArrow | Moves the current cell to previous to the active current cell. If the CurrentCell is in first cell, pressing 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 last cell, pressing RightArrow does nothing. If the focused row is group header, the group will 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 SfDataGrid will be scrolled to next set of rows that are not displayed in view, including the row that are partially displayed and the current cell is set to last row. |
PageUp | The SfDataGrid will be scrolled to previous set of rows that are not displayed in view, including the row that are 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 moved to 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 to the active current cell. If the active current cell is the first cell of the current row, the current cell will moved to 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 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 committed and moves the current cell to below the active current cell. If the active current cell is in last row, commits changes only and retains in the same cell. |
Ctrl + Enter | Commits only the changes when the current cell 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 the , on pressing of Esc key for the second time will cancel the edit mode for entire row. |
Delete | If the current cell is not in edit mode, the current row will be deleted. |
Ctrl + A | All rows or cells will be selected. |
NOTE
When the NavigationMode is in Row, the RightArrow and LeftArrow only work for grouping headers and the following keys Tab, Shift + Tab, Delete, Home, End will not work.
Shift Key Combinations
When the SelectionMode is set to Extended, you can select multiple rows or cells using the navigation keys along with the Shift key. Before navigation starts, the current cell will be marked as a pressed cell and the selection will be done in all rows or cells between the pressed cell and current cell.
Key Combinations |
---|
Shift + DownArrow |
Shift + UpArrow |
Shift + RightArrow |
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/disable the selection when the mouse button is in pressed state by setting the AllowSelectionOnPointerPressed property.
When the SelectionMode is set to Extended, you can select multiple rows or cells by clicking on any cell along with ctrl and Shift key. When you click a cell along with Ctrl key, you can select or deselect the particular row or cell. When you click a cell along with Shift key, you can select the range rows or cells from the pressed cell to the current cell.
Customizing mouse and keyboard behaviors
You can customize mouse and keyboard behaviors by overriding the selection controller. You can refer the section Customizing Selection Behaviors to override the selection controller.
Events Processed on Selection
CurrentCellActivating Event
The CurrentCellActivating event will occurs before moving the current cell to particular cell. CurrentCellActivatingEventArgs has following members which provides information for CurrentCellActivatingEvent
.
-
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 was move.
<syncfusion:SfDataGrid x:Name="dataGrid"
CurrentCellActivating="dataGrid_CurrentCellActivating"
ItemsSource="{Binding Orders}">
this.dataGrid.CurrentCellActivating += dataGrid_CurrentCellActivating;
void dataGrid_CurrentCellActivating(object sender, CurrentCellActivatingEventArgs args)
{
}
You can cancel the current cell moving process within this event by setting GridCurrentCellActivatingEventArgs.Cancel as true.
void dataGrid_CurrentCellActivating(object sender, CurrentCellActivatingEventArgs args)
{
var provider = this.dataGrid.View.GetPropertyAccessProvider();
var record = this.dataGrid.GetRecordAtRowIndex(args.CurrentRowColumnIndex.RowIndex);
if (record == null)
return;
var column = this.dataGrid.Columns[this.dataGrid.ResolveToGridVisibleColumnIndex(args.CurrentRowColumnIndex.ColumnIndex)];
var cellValue = provider.GetValue(record, column.MappingName);
if (cellValue.ToString() == "1001")
args.Cancel = true;
}
CurrentCellActivated Event
The CurrentCellActivated event will occur once the current cell is moved to corresponding cell. CurrentCellActivatedEventArgs has following members which provides information for CurrentCellActivated
event.
-
ActivationTrigger – Returns the reason of the current cell movement.
-
CurrentRowColumnIndex –
RowColumnIndex
of the cell where the current cell was moved. -
PreviousRowColumnIndex –
RowColumnIndex
of the cell from where the current cell has been moved.
<syncfusion:SfDataGrid x:Name="dataGrid"
CurrentCellActivated="dataGrid_CurrentCellActivated"
ItemsSource="{Binding Orders}">
this.dataGrid.CurrentCellActivated += dataGrid_CurrentCellActivated;
void dataGrid_CurrentCellActivated(object sender, CurrentCellActivatedEventArgs args)
{
}
SelectionChanging Event
SelectionChanging event occurs before processing the selection to particular row or cell. This event will be triggered only to the keyboard and mouse interactions. GridSelectionChangingEventArgs has the following members which provides the information for SelectionChanging
event.
-
AddedItems – Collection of GridRowInfo or GridCellInfo where the selection going to process.
-
RemovedItems – Collection of
GridRowInfo
orGridCellInfo
where the selection going to remove.
<syncfusion:SfDataGrid x:Name="dataGrid"
SelectionChanging="dataGrid_SelectionChanging"
ItemsSource="{Binding Orders}">
this.dataGrid.SelectionChanging += dataGrid_SelectionChanging;
void dataGrid_SelectionChanging(object sender, GridSelectionChangingEventArgs e)
{
}
You can cancel the selection process within this event by setting GridSelectionChangingEventArgs.Cancel property as true.
private void Datagrid_SelectionChanging(object sender, GridSelectionChangingEventArgs e)
{
var unBoundRow = e.AddedItems.Where(rowInfo => (rowInfo as GridRowInfo).IsUnBoundRow).ToList();
if (unBoundRow.Count() > 0)
e.Cancel = true;
}
SelectionChanged Event
The SelectionChanged event will occurs once the selection process has been completed for particular row or cell in SfDataGrid. GridSelectionChangedEventArgs has following members which provides information for SelectionChanged
event.
-
AddedItems – Collection of GridRowInfo or GridCellInfo where the selection has been processed.
-
RemovedItems – Collection of
GridRowInfo
orGridCellInfo
from where the selection has been removed.
<syncfusion:SfDataGrid x:Name="dataGrid"
SelectionChanged="dataGrid_SelectionChanged"
ItemsSource="{Binding Orders}">
this.dataGrid.SelectionChanged += dataGrid_SelectionChanged;
void dataGrid_SelectionChanged(object sender, GridSelectionChangedEventArgs e)
{
}
Appearance
Changing Selection Background and Foreground
You can change the selection background and foreground using RowSelectionBrush, GroupRowSelectionBrush and SelectionForeGroundBrush properties. The RowSelectionBrush
is only applied to the rows other than summary rows and the GroupRowSelectionRows is applied for caption summary and group summary rows.
<syncfusion:SfDataGrid x:Name="dataGrid"
AllowGrouping="True"
ShowGroupDropArea="True"
RowSelectionBrush="#FFDFF3F4"
GroupRowSelectionBrush="#FFC8E3E3"
SelectionForegroundBrush="DarkBlue"
SelectionMode="Extended"
ItemsSource="{Binding Orders}">
Changing Current Cell Border Style
You can change the current cell border thickness and border color using CurrentCellBorderThickness and CurrentCellBorderBrush property.
<syncfusion:SfDataGrid x:Name="dataGrid"
CurrentCellBorderBrush="Red"
CurrentCellBorderThickness="1.6"
ItemsSource="{Binding Orders}">
Customizing Row Selection Border
You can customize the row selection by editing the control template of corresponding row controls.
-
Data Row / Add New Row
– VirtualizingCellsControl -
CaptionSummary Row
– CaptionSummaryRowControl -
GroupSummary Row
– GroupSummaryRowControl -
UnBound Row
– UnBoundRowControl -
Filter Row
- FilterRowControl
<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>
<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}" />
<Border Background="{TemplateBinding RowHoverBackgroundBrush}"
BorderBrush="{TemplateBinding RowHoverBackgroundBrush}"
BorderThickness="{TemplateBinding RowHighlightBorderThickness}"
Clip="{TemplateBinding HighlightBorderClipRect}"
SnapsToDevicePixels="True"
Visibility="{TemplateBinding HighlightSelectionBorderVisiblity}" />
<Rectangle Clip="{TemplateBinding RowBackgroundClip}"
Fill="{TemplateBinding Background}" />
<!-- Adding new border to show border for whole selected row -->
<Border x:Name="PART_SelectionBorder"
BorderBrush="Red"
BorderThickness="1.5,1.5,1.5,2.5"
Opacity="0.75"
Background="{TemplateBinding RowSelectionBrush}"
Clip="{TemplateBinding SelectionBorderClipRect}"
Visibility="{TemplateBinding SelectionBorderVisiblity}" />
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Customizing Cell Selection
You can customize the cell selection by editing the control template of the corresponding cell control.
-
DataRow / AddNewRow
– GridCell -
UnBound Row
– GridUnBoundRowCell -
Filter Row
- GridFilterRowCell
<Style TargetType="{x:Type syncfusion:GridCell}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Gray" />
<Setter Property="BorderThickness" Value="0,0,1,1" />
<Setter Property="Padding" Value="0,0,0,0" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type syncfusion:GridCell}">
<Grid SnapsToDevicePixels="True">
<Border Background="{TemplateBinding CellSelectionBrush}"
SnapsToDevicePixels="True"
Visibility="{TemplateBinding SelectionBorderVisibility}" />
<Border x:Name="PART_GridCellBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True">
<Grid>
<ContentPresenter Margin="{TemplateBinding Padding}" />
</Grid>
</Border>
<Border Background="Transparent"
BorderBrush="Red"
BorderThickness="0.5"
IsHitTestVisible="False"
SnapsToDevicePixels="True"
Margin="0,0,1,1"
Visibility="{TemplateBinding CurrentCellBorderVisibility}" />
<!—Adding new border to show inner border to the CurrentCellBorder -->
<Border Background="Transparent"
BorderBrush="Red"
BorderThickness="0.5"
IsHitTestVisible="False"
SnapsToDevicePixels="True"
Margin="2,2,3,3"
Visibility="{TemplateBinding CurrentCellBorderVisibility}" />
<Border x:Name="PART_InValidCellBorder"
Width="10"
Height="10"
HorizontalAlignment="Right"
Visibility="Collapsed"
VerticalAlignment="Top"
SnapsToDevicePixels="True">
<ToolTipService.ToolTip>
<ToolTip Background="#FFDB000C"
Placement="Right"
PlacementRectangle="20,0,0,0"
Tag="{TemplateBinding ErrorMessage}"
Template="{StaticResource ValidationToolTipTemplate}" />
</ToolTipService.ToolTip>
<Path Data="M0.5,0.5 L12.652698,0.5 12.652698,12.068006 z"
Fill="Red"
SnapsToDevicePixels="True"
Stretch="Fill" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Binding Selection Properties
You can bind the selection properties like SelectedItem, SelectedIndex and CurrentItem to the properties in ViewModel
directly.
<syncfusion:SfDataGrid x:Name="dataGrid"
SelectedItem="{Binding DataGridSelectedItem, Mode=TwoWay}"
CurrentItem="{Binding DataGridCurrentItem,Mode=TwoWay}"
SelectedIndex="{Binding DataGridSelectedIndex,Mode=TwoWay}"
ItemsSource="{Binding Orders}">
In DetailsView, it is not possible to bind selection properties directly with ViewModel. You can use Behavior to achieve this requirement.
<syncfusion:SfDataGrid x:Name="dataGrid"
AutoGenerateColumns="True"
ItemsSource="{Binding Orders}">
<interactivity:Interaction.Behaviors>
<!-- Binding code behind properties to SelectionBehavior dependency properties -->
<local:SelectionBehavior AttachedDetailsViewSelectedItem="{Binding DetailsViewSelectedItem, Mode=TwoWay}"
AttachedDetailsViewSelectedIndex="{Binding DetailsViewSelectedIndex,Mode=TwoWay}"
AttachedDetailsViewCurrentItem="{Binding DetailsViewCurrentItem, Mode=TwoWay}"
</interactivity:Interaction.Behaviors>
<syncfusion:GridViewDefinition RelationalColumn="OrdersDetailsFirstNested">
<syncfusion:GridViewDefinition.DataGrid>
<syncfusion:SfDataGrid x:Name="FirstDetailsViewGrid"
AutoGenerateColumns="True"/>
</syncfusion:GridViewDefinition.DataGrid>
</syncfusion:GridViewDefinition>
</syncfusion:SfDataGrid>
public class SelectionBehavior : Behavior<SfDataGrid>
{
public object AttachedDetailsViewSelectedItem
{
get { return (object)GetValue(AttachedDetailsViewSelectedItemProperty); }
set { SetValue(AttachedDetailsViewSelectedItemProperty, value); }
}
public static readonly DependencyProperty AttachedDetailsViewSelectedItemProperty =
DependencyProperty.Register("AttachedDetailsViewSelectedItem", typeof(object), typeof(SelectionBehavior), new PropertyMetadata(null));
public object AttachedDetailsViewSelectedIndex
{
get { return (object)GetValue(AttachedDetailsViewSelectedIndexProperty); }
set { SetValue(AttachedDetailsViewSelectedIndexProperty, value); }
}
public static readonly DependencyProperty AttachedDetailsViewSelectedIndexProperty =
DependencyProperty.Register("AttachedDetailsViewSelectedIndex", typeof(object), typeof(SelectionBehavior), new PropertyMetadata(null));
public object AttachedDetailsViewCurrentItem
{
get { return (object)GetValue(AttachedDetailsViewCurrentItemProperty); }
set { SetValue(AttachedDetailsViewCurrentItemProperty, value); }
}
public static readonly DependencyProperty AttachedDetailsViewCurrentItemProperty =
DependencyProperty.Register("AttachedDetailsViewCurrentItem", typeof(object), typeof(SelectionBehavior), new PropertyMetadata(null));
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.Loaded += AssociatedObject_Loaded;
}
void AssociatedObject_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
(this.AssociatedObject.DetailsViewDefinition[0] as GridViewDefinition).DataGrid.SelectionChanged += DetailsViewDataGridSelectionChanged;
}
void DetailsViewDataGridSelectionChanged(object sender, GridSelectionChangedEventArgs e)
{
this.AttachedDetailsViewSelectedItem = (e.OriginalSender as SfDataGrid).SelectedItem;
this.AttachedDetailsViewSelectedIndex = (e.OriginalSender as SfDataGrid).SelectedIndex;
this.AttachedDetailsViewCurrentItem = (e.OriginalSender as SfDataGrid).CurrentItem;
}
protected override void OnDetaching()
{
base.OnDetaching();
this.AssociatedObject.Loaded -= AssociatedObject_Loaded;
}
}
You can get the sample from here
Customizing Selection Behaviors
The SfDataGrid process the selection operations in selection controller. Below are the built-in selection controllers,
-
GridSelectionController – Process selection operations when selection unit as row.
-
GridCellSelectionController – process selection operations when selection unit as cell or Any.
You can customize the default row selection behaviors by overriding GridSelectionController
class and set it to SfDataGrid.SelectionController
.
this.dataGrid.SelectionController = new GridSelectionControllerExt(this.dataGrid);
public class GridSelectionControllerExt:GridSelectionController
{
public GridSelectionControllerExt(SfDataGrid dataGrid):base(dataGrid)
{
}
}
Changing Enter Key Behavior
By default, while pressing Enter key the current cell will be moved to next focused cell in the same column. You can change the behavior by overriding the corresponding selection controllers based on SelectionUnit.
You can change the Enter key behavior by overriding ProcessKeyDown method in selection controller. In this method you have to create new KeyEventArgs which refers the Tab key and processes the Tab key action.
public class GridSelectionControllerExt:GridSelectionController
{
public GridSelectionControllerExt(SfDataGrid dataGrid):base(dataGrid)
{
}
protected override void ProcessKeyDown(KeyEventArgs args)
{
if (args.Key == Key.Enter)
{
//Creates new KeyEventArgs to refer the Tab key.
KeyEventArgs arguments = new KeyEventArgs(args.KeyboardDevice, args.InputSource, args.Timestamp, Key.Tab) { RoutedEvent = args.RoutedEvent };
//Base ProcessKeyDown is invoked to process Tab key operations.
base.ProcessKeyDown(arguments);
args.Handled = arguments.Handled;
return;
}
base.ProcessKeyDown(args);
}
}
Selecting all rows in a group when expanding
You can select all the rows in the group which is expanding through mouse click. To achieve this, you have to set SelectionMode as Extended or Multiple and also need to override HandlePointerOperations method in selection controller.
public class GridSelectionControllerExt:GridSelectionController
{
public GridSelectionControllerExt(SfDataGrid dataGrid)
:base(dataGrid)
{
}
public override void HandlePointerOperations(GridPointerEventArgs args, Syncfusion.UI.Xaml.ScrollAxis.RowColumnIndex rowColumnIndex)
{
base.HandlePointerOperations(args, rowColumnIndex);
if (args.Operation == PointerOperation.Released)
{
if (this.DataGrid.View.TopLevelGroup != null)
{
//Get the group from the DisplayElements by resolving record index of corresponding row index
var group = this.DataGrid.View.TopLevelGroup.DisplayElements[this.DataGrid.ResolveToRecordIndex(rowColumnIndex.RowIndex)];
if (group != null && group is Group)
SelectGroupRows(group as Group);
}
}
}
private void SelectGroupRows(Group group)
{
if (group == null || !group.IsExpanded)
return;
//Check whether the group contains inner level groups.
if (group.Groups == null)
{
//Get the corresponding start index of record by getting it from DisplayElements .
var startIndex = this.DataGrid.View.TopLevelGroup.DisplayElements.IndexOf(group as Group);
//Resolve the recordIndex to RowIndex.
var startRowIndex = this.DataGrid.ResolveToRowIndex(startIndex);
//Gets the count of rows in the group.
var count = group.ItemsCount + this.DataGrid.GroupSummaryRows.Count;
//Select the rows from corresponding start and end row index
this.DataGrid.SelectionController.SelectRows(startRowIndex, startRowIndex + count);
}
else
{
foreach (var gr in group.Groups)
{
//Called recursively, to traverse it inner level of group.
SelectGroupRows(gr);
var startIndex = this.DataGrid.View.TopLevelGroup.DisplayElements.IndexOf(group as Group);
var startRowIndex = this.DataGrid.ResolveToRowIndex(startIndex);
//Get the corresponding end index of the group by getting it from DisplayElements using the inner level group.
var endIndex = this.DataGrid.View.TopLevelGroup.DisplayElements.IndexOf(gr as Group);
var endRowIndex = this.DataGrid.ResolveToRowIndex(endIndex);
this.DataGrid.SelectionController.SelectRows(startRowIndex, endRowIndex);
}
}
}
}
Selecting the column when clicking header
You can select entire column on clicking column header by handling MouseLeftButtonUp event of SfDataGrid. You have to set SelectionUnit as Cell or Any and SelectionMode as Extended or Multiple to achieve this behavior.
By default the sorting operation will be performed while clicking on column header where you can disable this action by setting AllowSorting as false or SortClickAction as DoubleClick.
<syncfusion:SfDataGrid x:Name="dataGrid"
SelectionUnit="Cell"
SortClickAction="DoubleClick"
SelectionMode="Extended"
ItemsSource="{Binding Orders}">
this.dataGrid.MouseLeftButtonUp += dataGrid_MouseLeftButtonUp;
private void dataGrid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount != 1)
return;
var visualContainer = this.dataGrid.GetVisualContainer();
//Getting row and column index from the current pointer position.
var rowColumnIndex = visualContainer.PointToCellRowColumnIndex(e.GetPosition(visualContainer));
var columnIndex = this.dataGrid.ResolveToGridVisibleColumnIndex(rowColumnIndex.ColumnIndex);
//Return if rowColumnIndex does not refer the HeaderCell
if (this.dataGrid.GetHeaderIndex() != rowColumnIndex.RowIndex || columnIndex < 0)
return;
//Gets the first record of the DataGrid.
var firstRowData = this.dataGrid.GetRecordAtRowIndex(dataGrid.GetFirstDataRowIndex());
//Gets the last record of the DataGrid.
var lastRowData = this.dataGrid.GetRecordAtRowIndex(dataGrid.GetLastDataRowIndex());
if (firstRowData == null || lastRowData == null)
return;
//Gets the column of the pointer position.
var column = this.dataGrid.Columns[columnIndex];
//Selects the entire column
this.dataGrid.SelectCells(firstRowData, column, lastRowData, column);
}
You can get the sample from here.
Avoid CaptionSummaryRow selection on Grouping
While grouping any column, by default the first CaptionSummaryRow will be selected when the CurrentItem is null. You can change this action by overriding the ProcessOnGroupChanged method in selection controller.
public class GridSelectionControllerExt : GridSelectionController
{
public GridSelectionControllerExt(SfDataGrid dataGrid) : base(dataGrid)
{
}
protected override void ProcessOnGroupChanged(GridGroupingEventArgs args)
{
base.ProcessOnGroupChanged(args);
var removedItems = new List<object>();
//Refresh the selection only in record rows.
this.RefreshSelectedItems(ref removedItems);
//Updates the current cell and current row.
this.UpdateCurrentRowIndex();
}
}
See Also
How to disable the row selection while clicking on the checkbox column
How to copy active cell value alone when SelectionUnit as Row
How to improve the performance while selecting rows using Shift key ?
How to scroll and select record programmatically ?
How to prevent the selection while pressing rightclick ?
How to get the SelectedItem of the DetailsView?
How to add a new row continuously in AddNewRow without moving the selection to next row?
How to change the CheckBoxColumn values based on row selection?
How to bind SelectedItem and CurrentItem in DetailsViewDataGrid
How to select the rows based on a CellValue?
How to change the cell value of selectedcells when end edit?
How to clear selection while grouping/ungrouping?
How to search and select record in SfDataGrid?
How to read cell values from SelectedItems?
How to add a new record in specific DetailsViewDataGrid ?
How to move selection to newly added record using AddNewRow?
How to programmatically select the records of the Master-DetailsView at run time?
How to accomplish RecordNavigationBar in the SfDataGrid like Syncfusion Windows Forms DataBoundGrid?
How to select the entire column in SfDataGrid ?
How to add selection to data rows of each group on expanding its CaptionSummaryRow?
How to change the Enter key behavior in SfDataGrid?
How to change the Enter key behavior to insert line break when the CurrentCell is in the edit mode?
How to show the selection of row/cell when setting the background for SfDataGrid GridCell?
How to set Border for the Selected Rows?
How to bind the SelectedItems property of SfDataGrid to ViewModel property?
How to get information from the selected cells when using cell selection?
How to avoid selection while grouping and ungrouping in SfDataGrid?
How to change the background and foreground for the selected row or cell?
How to set current cell on particular row when DataGrid loaded?