This blog is part of the utility implementation of C1FlexGrid for Winforms. As the title suggests, we will be avoiding setting the focus on cells marked as ReadOnly through tab movement, mouse click, or code. Any kind of action setting the focus on ReadOnly cells moves the focus to the next or previous editable cell. Lets quickly start with the implementation section.
C1FlexGrid does not have a feature that directly sets a cell as ReadOnly, and in order to do so, we have to 'tag' the cell as ReadOnly. We can set the value of 'UserData' property of the cell as 'Locked.' We can later use this property to determine if the cell is marked as ReadOnly.
' Maintains the list of non editable cells Public noneditablelist As New List(Of C1.Win.C1FlexGrid.CellRange) Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load flex.Cols.Count = 6 flex.Rows.Count = 10 flex.KeyActionTab = C1.Win.C1FlexGrid.KeyActionEnum.MoveAcrossOut flex.KeyActionEnter = C1.Win.C1FlexGrid.KeyActionEnum.MoveAcrossOut noneditablelist.Add(flex.GetCellRange(1, 2)) noneditablelist.Add(flex.GetCellRange(1, 4)) noneditablelist.Add(flex.GetCellRange(2, 2)) noneditablelist.Add(flex.GetCellRange(3, 3)) noneditablelist.Add(flex.GetCellRange(3, 5)) noneditablelist.Add(flex.GetCellRange(5, 4)) noneditablelist.Add(flex.GetCellRange(4, 3)) noneditablelist.Add(flex.GetCellRange(6, 2)) noneditablelist.Add(flex.GetCellRange(4, 1)) ' Marks Tag for each non editable cell as Locked and ' change back color For Each lc As C1.Win.C1FlexGrid.CellRange In noneditablelist lc.StyleNew.BackColor = Color.LightGreen flex.SetUserData(lc.r1, lc.c1, "Locked") Next End Sub
This section of code determines which cell will receive the focus when focus is changed using Tab, Enter, Direction keys, or mouse. BeforeSelChange() event is used for all the code execution.
' Variable to be used for determining Cell Change Dim allowmove As Boolean = False Private Sub flex_BeforeSelChange(sender As Object, e As C1.Win.C1FlexGrid.RangeEventArgs) Handles flex.BeforeSelChange If allowmove = True Then allowmove = False Exit Sub End If Dim row As Integer = e.NewRange.r1 Dim col As Integer = e.NewRange.c1 While Not allowmove If flex.GetUserData(row, col) = "Locked" Then ' if the current Column is ReadOnly, ' increase the Column index to next Column or previous Column If e.NewRange.r1 > e.OldRange.r1 Then col += 1 ElseIf e.NewRange.r1 < e.OldRange.r1 Then col -= 1 Else If e.NewRange.c1 >= e.OldRange.c1 Then col += 1 Else col -= 1 End If End If ' Reposition the Focus to next Row, if Col is equal to last column of the Grid. If col >= flex.Cols.Count Then ' Reposition the Row to 1st Row if 'Row' is equal to last row of the Grid. If row = flex.Rows.Count - 1 Then row = flex.Rows.Fixed Else row += 1 End If col = flex.Cols.Fixed ' Reposition the Focus to previous Row, if Col is equal to fixed columns of the Grid. ElseIf col <= flex.Cols.Fixed - 1 Then row -= 1 col = flex.Cols.Count - 1 End If Else allowmove = True End If End While ' Cancel the default Row Movement e.Cancel = True ' Move focus to the next Editable Cell flex.Select(row, col) End Sub
Once you have the above code implemented correctly, cells marked as ReadOnly will not receive the focus. However, if you double click on these cells, they get into edit mode. Thus, we have to supress the double click action on these cells.
' Cancel double click event on non editable cells Private Sub flex_BeforeDoubleClick(sender As Object, e As C1.Win.C1FlexGrid.BeforeMouseDownEventArgs) Handles flex.BeforeDoubleClick Dim hti As C1.Win.C1FlexGrid.HitTestInfo = flex.HitTest(e.X, e.Y) If noneditablelist.Contains(flex.GetCellRange(hti.Row, hti.Column)) Then e.Cancel = True End If End Sub
You can download the complete sample from the given link. Download Sample