0

I want to have a table displayed on a DataGridView with multiple columns, all of them on readonly but one. This one column needs to have the capacity of being filled by the user, but I want to make the cells that already have content on them ReadOnly, not all the column so the user will still have the capacity of fill the remaining cells on the column (with the exception of the ones that already have been filled)

Is there a way to achieve this?

Miguel V
  • 606
  • 2
  • 6
  • 18
  • See the [ReadOnly](https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.datagridviewcell.readonly?view=netframework-4.8) property – Mark Benningfield Oct 15 '21 at 13:55
  • Look into the [CellBeginEdit](https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.datagridview.cellbeginedit?view=windowsdesktop-5.0) event. The event sparks when a cell is being edited, so you can set your `ReadOnly` properties in there under your conditions. – The2Step Oct 15 '21 at 14:06
  • Agree with The2Step, but possibly simpler; cancel the BeginEdit event if you don't want the user editing the cell. You can also look at EditingControlShowing, and make the editing textbox readonly if it's not the right cell – Caius Jard Oct 15 '21 at 16:12

1 Answers1

3

You can set CellEndEdit event simply like this:

private void DataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    DataGridViewCell cell =        this.DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex);
    cell.ReadOnly = true;
}

VB.NET:

Private Sub DataGridView1_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
    Dim cell As DataGridViewCell = Me.DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex)
    cell.ReadOnly = True
End Sub

And if you have data in the DataGridView at the beginning, you can set the access after you load the data like this:

SetAccess(this.DataGridView1);

VB.NET:

Call SetAccess(Me.DataGridView1)

...providing this function in your class:

private void SetAccess(DataGridView dgw)
{
    for (var ir = 0; ir <= dgw.Rows.Count - 1; ir++)
    {
        for (var ic = 0; ic <= dgw.Columns.Count - 1; ic++)
        {
            DataGridViewCell cell = this.DataGridView1.Rows(ir).Cells(ic);
            if (!IsNothing(cell.Value) && cell.Value.ToString.Length > 0)
                cell.ReadOnly = true;
        }
    }
}

VB.NET:

Private Sub SetAccess(dgw As DataGridView)
    For ir = 0 To dgw.Rows.Count - 1
        For ic = 0 To dgw.Columns.Count - 1
            Dim cell As DataGridViewCell = Me.DataGridView1.Rows(ir).Cells(ic)
            If Not IsNothing(cell.Value) AndAlso cell.Value.ToString.Length > 0 Then
                cell.ReadOnly = True
            End If
        Next
    Next
End Sub

Tested, all works as a charm.

Obviously you can play with the code, i.e. excluding the last column by modifying the range of column loop:

For ic = 0 To dgw.Columns.Count - 2

VB.NET (same):

For ic = 0 To dgw.Columns.Count - 2

Sorry, missed the c# tag when replied first.

Oak_3260548
  • 1,882
  • 3
  • 23
  • 41
  • This works pretty good, really liked the explanation, specially because it's on my plan to have data in the DGV at the start of the operation in later versions of the project! Don't worry about the explanation in VB.NET, it's actually cool to see the differences and similarities between both programming languages – Miguel V Oct 15 '21 at 18:31