15
votes

I have a binded DataGridView that contains a large amount of data. The problem is that some cells has to be ReadOnly and also when the user navigates with TAB or ENTER between cells, the ReadOnly cells should be bypassed. What's the best way of making some specific cells ReadOnly imediatly after loadging?

Looping through cells after I set DataSource is not a good idea taking in consideration that the grid has a large amount of data. Also, making the cell ReadOnly on CellEnter does not work because when navigating with TAB key I have to already know if the next cell is ReadOnly or not.

9

9 Answers

24
votes

Try to make the column rather than individual cells readonly before binding the data:

this.dgrid.Columns["colName"].ReadOnly = true;

If you need to do for individual cells within the column, then you will have to loop and set them like this:

this.dgridvwMain.Rows[index].Cells["colName"].ReadOnly = true;
4
votes

You can use CellBeginEdit event and set e.Cancel = True when you need disable the cell.

Private Sub DataGridView_CellBeginEdit(sender As System.Object, e As System.Windows.Forms.DataGridViewCellCancelEventArgs) Handles DataGridViewMsg.CellBeginEdit
    If DataGridViewMsg.Rows(e.RowIndex).Cells("disable").Value = "Y" Then
        e.Cancel = True
    End If
End Sub
2
votes

I haven't tried this.

But, you could set the cell's readonly property to true (as per Rashmi), on RowEnter event?

I guess RowEnter event should fire when you move from one row to the other (or it should when you change from cell A1 to B3).

Does that help at all?

2
votes
this.dataGridViewEmpList.EditMode = DataGridViewEditMode.EditProgrammatically;
1
votes

I iterated through the datagrid with the following code:

dataGridViewTest.DataSource = persons;

foreach (DataGridViewRow row in dataGridViewTest.Rows)
{
    foreach (DataGridViewCell cell in row.Cells)
    {
        if (cell.Value.ToString() == "John")
        {
            cell.ReadOnly = true;
        }
    }
}
0
votes

Once the column is read only (see Rashmi's response) you can handle this event...

private void dataGridView1_KeyPress(object sender, KeyPressEventArgs e)
{
    if (e.KeyChar == (char)Keys.Tab)
    {
        Boolean readOnly = (sender as DataGridView).SelectedCells[0].ReadOnly;

        return;
    }

}

Which will get the next cell's read only property.

Thanks

0
votes

You can do this using the BeginningEdit event to check if the check if the cell meets a condition and cancel the operation if not:

In the example below, if the cell already contains a value it will cancel the operation, deeming it as read only.

xaml:

<DataGrid BeginningEdit="DataGrid_BeginningEdit" ItemsSource="{Binding Example, Mode=TwoWay}"/>

c#:

private void DataGrid_BeginningEdit(object sender, DataGridBeginningEditEventArgs e)
{
    string content = (e.EditingEventArgs.Source as TextBlock).Text;

    if (!(String.IsNullOrEmpty(content)))
        e.Cancel = true;
}
-1
votes

Could you not use a template column instead of a bound column then have a condition for the readonlyness of the field?

Then you could present a label for readonly and a textbox for editable. Labels would not interfere with your tab index.

<asp:TemplateColumn>
  <ItemTemplate>
<%
    if ( <%# Eval( "ReadOnlyFlag" ) %> )
    { 
%>
    <asp:Label Text="<%# Eval( "BoundColumn" ) %>" />
<%
    }
    else
    {
 %>
    <asp:Textbox Text="<%# Eval( "BoundColumn" ) %>" />
<%
    }
%>
    </ItemTemplate>
</asp:TemplateColumn>
-2
votes

There's a very nice sample here:
http://blogs.msdn.com/netcfteam/archive/2006/04/25/583542.aspx

You just need to override Paint() , I've used this on compact framework to change the backcolor depending on the cell contents so on the same note you shouldn't have any problem to set them read only.