1
votes

DataGridViewComboBoxCell.ReadOnly = true, but can still change the selected value has the same question but user was satisfied with an answer I can't implement.

I got a dataGridView with many columns, one of which is a checkBoxColumn, which should activate or deactivate another column with text:

enter image description here

Now, the code I got works perfect once the dataGridView is loaded: I click on the checkboxes and they work as expected.

The problem is that I want the dataGridView to disable AllergiesDescription cells that don't have their corresponding Allergies cell checked in load time. I wrote a code that should iterate over the rows and execute the disable cell code whenever an unchecked Allergies cell is found. But against all odds, it doesn't work! It sets all wanted properties to the cell (like readonly = true) but still the cell is editable:

enter image description here

Sharing my code here below:

    private void dataGridView_CellContentClick(object sender,
        DataGridViewCellEventArgs cellEvent)
    {
        if (cellEvent.ColumnIndex == AllergiesCheckBoxColumn.Index)
            toggleAllergiesDescriptionHabilitation(cellEvent.RowIndex);
    }

    private void toggleAllergiesDescriptionHabilitation(int rowIndex)
    {
        int columnIndex = AllergiesDescriptionTextBoxColumn.Index;
        DataGridViewRow row = dataGridView.Rows[rowIndex];
        var allergiesDescriptionCell = (DataGridViewTextBoxCell)row.Cells[columnIndex];
        var currentCell = (DataGridViewCheckBoxCell)dataGridView.CurrentCell;
        if ((bool)currentCell.EditedFormattedValue)
            enableCell(allergiesDescriptionCell);
        else
            disableCell(allergiesDescriptionCell);
    }

    private void enableCell(DataGridViewTextBoxCell cell)
    {
        cell.ReadOnly = false;
        cell.Style.BackColor = Color.White;
        cell.Style.ForeColor = Color.Black;
        cell.Style.SelectionBackColor = Color.Blue;
        cell.Style.SelectionForeColor = Color.White;
    }

    private void disableCell(DataGridViewTextBoxCell cell)
    {
        cell.ReadOnly = true;
        cell.Style.BackColor = Color.LightGray;
        cell.Style.ForeColor = Color.DarkGray;
        cell.Style.SelectionBackColor = Color.LightGray;
        cell.Style.SelectionForeColor = Color.DarkGray;
    }

That code works perfect as I said, whenever I check an Allergies checkBox the corresponding AllergiesDescription cell enables or disables as expected. But:

    public People(PersistenceManager persistenceManager)
    {
        InitializeComponent();
        //other stuff
        disableNotCheckedAllergiesDescription();
    }

    private void disableNotCheckedAllergiesDescription()
    {
        foreach (DataGridViewRow row in dataGridView.Rows)
        {
            Person person = (Person)row.DataBoundItem;
            if (person != null && !person.Allergies)
                disableNotCheckedAllergiesDescription(row);
        }
    }

    private void disableNotCheckedAllergiesDescription(DataGridViewRow row)
    {
        int columnIndex = AllergiesDescriptionTextBoxColumn.Index;
        var allergiesDescriptionCell = (DataGridViewTextBoxCell)row.Cells[columnIndex];
        disableCell(allergiesDescriptionCell);
    }

This doesn't work, as you can see, it only executes the disableCell code for each cell that should be disabled, when I debug, the unchecked rows enter the method disableCell correctly, and their readonly value is set to true correctly, but they are still editable.

1
A workaround would also helpLoaderon
Try calling disableNotCheckedAllergiesDescription(); not in the constructor, but in the load or shown event.LarsTech
You are a genius! I called disableNotCheckedAllergiesDescription() inside of dataGridView DataBindingComplete event, which obviously means I was disabling the cell before the data binding took place. Thanks man! post your answer and I will select it.Loaderon

1 Answers

2
votes

Setting the ReadOnly property of the DataGridViewCells seems to come too early when you call it from inside the constructor. Try moving this call:

disableNotCheckedAllergiesDescription();

to the DataBindingComplete event instead.

private void dgv_DataBindingComplete(object sender, 
                                     DataGridViewBindingCompleteEventArgs e) {
  disableNotCheckedAllergiesDescription();
}