Skip to main content Skip to footer

Skipping Focus on Readonly Cells

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