To reproduce: private void Form1_Load(object sender, EventArgs e) { // TODO: This line of code loads data into the 'nwindDataSet.Products' table. You can move, or remove it, as needed. this.productsTableAdapter.Fill(this.nwindDataSet.Products); // TODO: This line of code loads data into the 'nwindDataSet.Order_Details' table. You can move, or remove it, as needed. this.order_DetailsTableAdapter.Fill(this.nwindDataSet.Order_Details); // TODO: This line of code loads data into the 'nwindDataSet.Categories' table. You can move, or remove it, as needed. this.categoriesTableAdapter.Fill(this.nwindDataSet.Categories); radGridView1.DataSource = nwindDataSet.Categories; GridViewTemplate firstChildtemplate = new GridViewTemplate(); firstChildtemplate.DataSource = nwindDataSet.Products; firstChildtemplate.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill; radGridView1.MasterTemplate.Templates.Add(firstChildtemplate); GridViewRelation relation = new GridViewRelation(radGridView1.MasterTemplate); relation.ChildTemplate = firstChildtemplate; relation.RelationName = "CategoriesProducts"; relation.ParentColumnNames.Add("CategoryID"); relation.ChildColumnNames.Add("CategoryID"); radGridView1.Relations.Add(relation); GridViewTemplate secondChildtemplate = new GridViewTemplate(); secondChildtemplate.DataSource = nwindDataSet.Order_Details; secondChildtemplate.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill; firstChildtemplate.Templates.Add(secondChildtemplate); GridViewRelation relation2 = new GridViewRelation(firstChildtemplate); relation2.ChildTemplate = secondChildtemplate; relation2.RelationName = "ProductsOrderDetails"; relation2.ParentColumnNames.Add("ProductID"); relation2.ChildColumnNames.Add("ProductID"); radGridView1.Relations.Add(relation2); this.radGridView1.AutoSizeColumnsMode = Telerik.WinControls.UI.GridViewAutoSizeColumnsMode.Fill; this.radGridView1.MultiSelect = true; this.radGridView1.SelectionMode = Telerik.WinControls.UI.GridViewSelectionMode.CellSelect ; } Please refer to the attached gif file illustrating the error when performing multiple selection. 1. Workaround: use Shift + arrow keys to perform multiple selection. 2. Workaround: custom row behavior: BaseGridBehavior behavior = (BaseGridBehavior)this.radGridView1.GridBehavior; behavior.UnregisterBehavior(typeof(GridViewHierarchyRowInfo)); behavior.RegisterBehavior(typeof(GridViewHierarchyRowInfo), new MyGridRowBehavior()); public class MyGridRowBehavior : GridHierarchyRowBehavior { protected override bool ProcessMouseSelection(Point mousePosition, GridCellElement currentCell) { if (this.RootGridBehavior.LockedBehavior != this) { this.GridControl.Capture = true; this.RootGridBehavior.LockBehavior(this); } bool result = this.DoMouseSelection(currentCell, mousePosition); return result; } private bool DoMouseSelection(GridCellElement currentCell, Point currentLocation) { if (!this.MasterTemplate.MultiSelect || this.GridViewElement.Template.AllowRowReorder) { return false; } Point mouseDownLocation = (Point)typeof(GridRowBehavior).GetField("mouseDownLocation", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this); Rectangle rect = new Rectangle(mouseDownLocation.X - SystemInformation.DragSize.Width / 2, mouseDownLocation.Y - SystemInformation.DragSize.Height / 2, SystemInformation.DragSize.Width, SystemInformation.DragSize.Height); if (rect.Contains(currentLocation)) { return false; } GridTableElement tableElement = this.GridViewElement.CurrentView as GridTableElement; if (tableElement == null) { return false; } bool selectionStartedOnAPinnedColumn = (bool)typeof(GridRowBehavior).GetField("selectionStartedOnAPinnedColumn", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this); bool mouseDownOnLeftPinnedColumn = (bool)typeof(GridRowBehavior).GetField("mouseDownOnLeftPinnedColumn", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this); bool mouseDownOnRightPinnedColumn = (bool)typeof(GridRowBehavior).GetField("mouseDownOnRightPinnedColumn", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this); bool selectionStartedOnAPinnedRow = (bool)typeof(GridRowBehavior).GetField("selectionStartedOnAPinnedRow", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this); bool mouseDownOnTopPinnedRow = (bool)typeof(GridRowBehavior).GetField("mouseDownOnTopPinnedRow", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this); bool mouseDownOnBottomPinnedRow = (bool)typeof(GridRowBehavior).GetField("mouseDownOnBottomPinnedRow", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this); if (selectionStartedOnAPinnedColumn && this.GetViewportBounds(tableElement).Contains(currentLocation)) { if (mouseDownOnLeftPinnedColumn) { tableElement.HScrollBar.Value = tableElement.HScrollBar.Minimum; mouseDownOnLeftPinnedColumn = false; } if (mouseDownOnRightPinnedColumn) { tableElement.HScrollBar.Value = tableElement.HScrollBar.Maximum - tableElement.HScrollBar.LargeChange + 1; mouseDownOnRightPinnedColumn = false; } selectionStartedOnAPinnedColumn = false; } if (selectionStartedOnAPinnedRow && this.GetViewportBounds(tableElement).Contains(currentLocation)) { if (mouseDownOnTopPinnedRow) { tableElement.VScrollBar.Value = tableElement.VScrollBar.Minimum; mouseDownOnTopPinnedRow = false; } if (mouseDownOnBottomPinnedRow) { tableElement.VScrollBar.Value = tableElement.VScrollBar.Maximum - tableElement.VScrollBar.LargeChange + 1; mouseDownOnBottomPinnedRow = false; } selectionStartedOnAPinnedRow = false; } if (currentCell.RowInfo is GridViewDataRowInfo) { if (this.MasterTemplate.SelectionMode == GridViewSelectionMode.FullRowSelect) { typeof(GridHierarchyRowBehavior).GetMethod("DoMultiFullRowSelect", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(this, new object[] { currentCell, currentLocation }); } else { this.DoMultiCellSelect(currentCell, currentLocation); } } return true; } private GridRowElement GetFirstScrollableRowElement(GridTableElement tableElement) { if (tableElement.ViewElement.ScrollableRows.Children.Count < 1) { return null; } return (GridRowElement)tableElement.ViewElement.ScrollableRows.Children[0]; } private GridViewColumn GetFirstScrollableColumn(GridTableElement tableElement) { GridRowElement rowElement = this.GetFirstScrollableRowElement(tableElement); if (rowElement == null) { return null; } int counter = 0; while (counter < rowElement.VisualCells.Count) { if (!rowElement.VisualCells[counter].IsPinned && rowElement.VisualCells[counter].ColumnInfo is GridViewDataColumn) { return rowElement.VisualCells[counter].ColumnInfo; } counter++; } return null; } private int GetRowIndex(GridViewRowInfo rowInfo) { List<GridViewRowInfo> orderedRows = typeof(GridRowBehavior).GetField("orderedRows", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this) as List<GridViewRowInfo>; return orderedRows.IndexOf(rowInfo); } private void DoMultiCellSelect(GridCellElement currentCell, Point currentLocation) { #region GridViewSelection int rowUnderMouseIndex = this.GetRowIndex(this.RootGridBehavior.RowAtPoint.RowInfo); int columnUnderMouseIndex = 0; GridTableElement tableElement = this.GridViewElement.CurrentView as GridTableElement; GridViewColumn col = this.RootGridBehavior.CellAtPoint.ColumnInfo; if (this.RootGridBehavior.CellAtPoint.ColumnInfo is GridViewRowHeaderColumn) { col = this.GetFirstScrollableColumn(tableElement); } List<GridViewRowInfo> orderedRows = typeof(GridRowBehavior).GetField("orderedRows", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this) as List<GridViewRowInfo>; List<GridViewColumn> orderedColumns = typeof(GridRowBehavior).GetField("orderedColumns", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this) as List<GridViewColumn>; if (col != null) { columnUnderMouseIndex = orderedColumns.IndexOf(col); } List<GridViewRowInfo> rows = new List<GridViewRowInfo>(); int anchorRowIndex = (int)typeof(GridRowBehavior).GetField("anchorRowIndex", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this); int startIndex = Math.Min(anchorRowIndex, rowUnderMouseIndex); int endIndex = Math.Max(anchorRowIndex, rowUnderMouseIndex); for (int i = startIndex; i < endIndex; i++) { if (i < 0) { continue; } if (this.GridViewElement.Template.ChildRows.Count > i) { rows.Add(orderedRows[i]); } } int anchorColumnIndex = (int)typeof(GridRowBehavior).GetField("anchorColumnIndex", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this); int columnLeft = Math.Min(anchorColumnIndex, columnUnderMouseIndex); int columnRight = Math.Max(anchorColumnIndex, columnUnderMouseIndex); GridViewSelectionCancelEventArgs cancelArgs = new GridViewSelectionCancelEventArgs(rows, columnLeft, columnRight); this.MasterTemplate.EventDispatcher.RaiseEvent<GridViewSelectionCancelEventArgs>(EventDispatcher.SelectionChanging, this, cancelArgs); if (cancelArgs.Cancel) { return; } #endregion bool isProcessedShiftOrControl = this.IsPressedShift || this.IsPressedControl; ObservableCollection<GridViewCellInfo> SelectedCells = typeof(GridViewSelectedCellsCollection).GetProperty("ObservableItems", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this.MasterTemplate.SelectedCells) as ObservableCollection<GridViewCellInfo>; SelectedCells.BeginUpdate(); this.GridViewElement.CurrentView.BeginUpdate(); int count = this.MasterTemplate.SelectedCells.Count; bool notifyUpdates = this.ProcessCellSelection(rowUnderMouseIndex, columnUnderMouseIndex); if (isProcessedShiftOrControl) { notifyUpdates = count != this.MasterTemplate.SelectedCells.Count; } this.GridViewElement.CurrentView.EndUpdate(false); SelectedCells.EndUpdate(notifyUpdates); } private bool ProcessCellSelection(int rowUnderMouseIndex, int columnUnderMouseIndex) { int currentRowIndex = (int)typeof(GridRowBehavior).GetField("currentRowIndex", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this); int anchorRowIndex = (int)typeof(GridRowBehavior).GetField("anchorRowIndex", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this); int currentColumnIndex = (int)typeof(GridRowBehavior).GetField("currentColumnIndex", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this); int anchorColumnIndex = (int)typeof(GridRowBehavior).GetField("anchorColumnIndex", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this); if ((rowUnderMouseIndex == currentRowIndex && columnUnderMouseIndex == currentColumnIndex) || (rowUnderMouseIndex < 0 || columnUnderMouseIndex < 0)) { return false; } bool verticalDirectionChange = (rowUnderMouseIndex < currentRowIndex && currentRowIndex > anchorRowIndex && rowUnderMouseIndex < anchorRowIndex) || (rowUnderMouseIndex > currentRowIndex && currentRowIndex < anchorRowIndex && rowUnderMouseIndex > anchorRowIndex); bool horizontalDirectionChange = (columnUnderMouseIndex < currentColumnIndex && currentColumnIndex > anchorColumnIndex && columnUnderMouseIndex < anchorColumnIndex) || (columnUnderMouseIndex > currentColumnIndex && currentColumnIndex < anchorColumnIndex && columnUnderMouseIndex > anchorColumnIndex); List<GridViewRowInfo> orderedRows = typeof(GridRowBehavior).GetField("orderedRows", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this) as List<GridViewRowInfo>; List<GridViewColumn> orderedColumns = typeof(GridRowBehavior).GetField("orderedColumns", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this) as List<GridViewColumn>; if (verticalDirectionChange || horizontalDirectionChange) { int rowStartIndex = Math.Min(anchorRowIndex, currentRowIndex); int rowEndIndex = Math.Max(anchorRowIndex, currentRowIndex); int colStartIndex = Math.Min(anchorColumnIndex, currentColumnIndex); int colEndIndex = Math.Max(anchorColumnIndex, currentColumnIndex); for (int i = rowStartIndex; i <= rowEndIndex; i++) { for (int j = colStartIndex; j <= colEndIndex; j++) { GridViewCellInfo cell = orderedRows[i].Cells[orderedColumns[j].Index]; if (cell != null && cell.IsSelected) { cell.IsSelected = false; } } } } bool expandingSelectionUp = rowUnderMouseIndex < currentRowIndex && rowUnderMouseIndex < anchorRowIndex; bool expandingSelectionDown = rowUnderMouseIndex > currentRowIndex && rowUnderMouseIndex > anchorRowIndex; bool expandingSelectionLeft = columnUnderMouseIndex < currentColumnIndex && columnUnderMouseIndex < anchorColumnIndex; bool expandingSelectionRight = columnUnderMouseIndex > currentColumnIndex && columnUnderMouseIndex > anchorColumnIndex; if (expandingSelectionDown || expandingSelectionUp || expandingSelectionLeft || expandingSelectionRight) { int rowStartIndex = Math.Min(anchorRowIndex, rowUnderMouseIndex); int rowEndIndex = Math.Max(anchorRowIndex, rowUnderMouseIndex); int colStartIndex = Math.Min(anchorColumnIndex, columnUnderMouseIndex); int colEndIndex = Math.Max(anchorColumnIndex, columnUnderMouseIndex); for (int i = rowStartIndex; i <= rowEndIndex; i++) { for (int j = colStartIndex; j <= colEndIndex; j++) { GridViewCellInfo cell = orderedRows[i].Cells[orderedColumns[j].Index]; if (cell != null && !cell.IsSelected) { cell.IsSelected = true; } } } } else { bool shrinkingSelectionUp = rowUnderMouseIndex < currentRowIndex && rowUnderMouseIndex >= anchorRowIndex; bool shrinkingSelectionDown = rowUnderMouseIndex > currentRowIndex && rowUnderMouseIndex <= anchorRowIndex; bool shrinkingSelectionLeft = columnUnderMouseIndex < currentColumnIndex && columnUnderMouseIndex >= anchorColumnIndex; bool shrinkingSelectionRight = columnUnderMouseIndex > currentColumnIndex && columnUnderMouseIndex <= anchorColumnIndex; if (shrinkingSelectionUp || shrinkingSelectionDown) { int rowStartIndex = Math.Min(currentRowIndex, rowUnderMouseIndex); int rowEndIndex = Math.Max(currentRowIndex, rowUnderMouseIndex); int colStartIndex = Math.Min(anchorColumnIndex, columnUnderMouseIndex); int colEndIndex = Math.Max(anchorColumnIndex, columnUnderMouseIndex); if (shrinkingSelectionUp) { rowStartIndex += 1; } if (shrinkingSelectionDown) { rowEndIndex -= 1; } for (int i = rowStartIndex; i <= rowEndIndex; i++) { if (i != anchorRowIndex) { for (int j = colStartIndex; j <= colEndIndex; j++) { GridViewCellInfo cell = orderedRows[i].Cells[orderedColumns[j].Index]; if (cell != null && cell.IsSelected) { cell.IsSelected = false; } } } } } if (shrinkingSelectionLeft || shrinkingSelectionRight) { int rowStartIndex = Math.Min(anchorRowIndex, rowUnderMouseIndex); int rowEndIndex = Math.Max(anchorRowIndex, rowUnderMouseIndex); int colStartIndex = Math.Min(currentColumnIndex, columnUnderMouseIndex); int colEndIndex = Math.Max(currentColumnIndex, columnUnderMouseIndex); if (shrinkingSelectionLeft) { colStartIndex += 1; } if (shrinkingSelectionRight) { colEndIndex -= 1; } for (int i = rowStartIndex; i <= rowEndIndex; i++) { for (int j = colStartIndex; j <= colEndIndex; j++) { if (j != anchorColumnIndex) { GridViewCellInfo cell = orderedRows[i].Cells[orderedColumns[j].Index]; if (cell != null && cell.IsSelected) { cell.IsSelected = false; } } } } } } typeof(GridRowBehavior).GetField("currentRowIndex", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(this, rowUnderMouseIndex); typeof(GridRowBehavior).GetField("currentColumnIndex", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(this, columnUnderMouseIndex); return true; } private Rectangle GetViewportBounds(GridTableElement tableElement) { ScrollableRowsContainerElement scrollableRows = tableElement.ViewElement.ScrollableRows; Rectangle bounds = tableElement.ViewElement.ScrollableRows.ControlBoundingRectangle; for (int index = 0; index < scrollableRows.Children.Count; index++) { GridVirtualizedRowElement virtualizedRow = scrollableRows.Children[index] as GridVirtualizedRowElement; if (virtualizedRow != null) { VirtualizedColumnContainer scrollableColumns = virtualizedRow.ScrollableColumns; bounds.X = this.GridViewElement.RightToLeft ? virtualizedRow.RightPinnedColumns.ControlBoundingRectangle.Right : virtualizedRow.LeftPinnedColumns.ControlBoundingRectangle.Right; bounds.Width = scrollableColumns.ControlBoundingRectangle.Width; break; } } return bounds; } }