Avoid setting the focus on cells marked as ReadOnly through tab movement, mouse click, or code. The goal is for any kind of action setting the focus on ReadOnly cells to move the focus to the next or previous editable cell.
Setting ReadOnly cells
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
Set focus on Next/Previous Editable Cell
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
Hunter Haaf