Reputation: 3271
I am working on an old .Net 2.0 WinForms project and need to set some cells to read only.
I have a DataTable that I am reading and setting as the DataSource and the field types are being set correctly
Generate DataTable and columns
public DataTable FilterData(DataTable datatable, string dataType)
{
try
{
if (dataType == "MailPreferences")
{
var dt = new DataTable();
dt.Columns.Add("SEQ_ID", typeof(int)); // SEQ_ID
dt.Columns.Add("MAIL_PREFERENCE_ID", typeof(string)); // MAIL_PREFERENCE_ID
dt.Columns.Add("Mail Preference Description", typeof(string)); // MAIL_PREFERENCE_DESC
dt.Columns.Add("Post", typeof(bool)); // POST
dt.Columns.Add("SMS", typeof(bool)); // SMS
dt.Columns.Add("Email", typeof(bool)); // EMAIL
dt.Columns.Add("Telephone", typeof(bool)); // TELEPHONE
foreach (DataRow row in datatable.Rows)
{
dt.Rows.Add(row["SEQ_ID"].ToString(),
row["MAIL_PREFERENCE_ID"].ToString(),
row["MAIL_PREFERENCE_DESC"].ToString(),
Convert.ToBoolean(row["POST"]),
Convert.ToBoolean(row["SMS"]),
Convert.ToBoolean(row["EMAIL"]),
Convert.ToBoolean(row["TELEPHONE"]));
}
return dt;
}
}
catch (Exception ex)
{
// catch and deal with my exception here
}
return null;
}
The above method is being called here and this is where I am having the issue of disabling cells.
private void PopulateMailPreferencesGV()
{
var dt = FilterData(_cAddPersonWizard.GetMailPreferneces(), "MailPreferences");
dgvMailPreferences.DataSource = dt;
dgvMailPreferences.Columns["Mail Preference Description"].Width = 250;
dgvMailPreferences.Columns["Post"].Width = 50;
dgvMailPreferences.Columns["SMS"].Width = 50;
dgvMailPreferences.Columns["Email"].Width = 50;
dgvMailPreferences.Columns["Telephone"].Width = 75;
dgvMailPreferences.Columns["SEQ_ID"].Visible = false;
dgvMailPreferences.Columns["MAIL_PREFERENCE_ID"].Visible = false;
// not setting the datagridview cell to readonly
foreach (DataGridViewRow row in dgvMailPreferences.Rows)
{
foreach (DataGridViewCell cell in row.Cells)
{
if (cell.GetType() == typeof(DataGridViewCheckBoxCell))
{
if(((DataGridViewCheckBoxCell)row.Cells[cell.ColumnIndex]).Selected == false)
{
((DataGridViewCheckBoxCell)row.Cells[cell.ColumnIndex]).ReadOnly = true;
}
}
}
}
}
When stepping through and looking at the Watch window I can see that the read only properties are being set, however when coming to work with the DataGridView the cells are still active.
I would be grateful if someone could point me in the direction of where this code is wrong or if I need to do something else?
Thanks for your help.
--- Edit 31/05/2017
The image above shows the grid that I want to work with, the options that are selected are selected by default.
The options that are not selected are to be disabled because these forms of delivery are not possible for the mail type
Upvotes: 10
Views: 3062
Reputation: 939
EDIT:
Ok I realised that the fiddle code wasn't yours (I should have read more carefully). I was able to recreate this using the code from your question. I see what the problem is now, it is this line:
if(((DataGridViewCheckBoxCell)row.Cells[cell.ColumnIndex]).Selected == false)
You are testing against 'Selected' which is not what you want, you want to test against the 'Value' of the cell.
If you look at the code in the other answers this is what they show.
Original Answer: Left for others
Running your code (fiddle) the checkboxes are indeed readonly although they do not appear grayed out as if they were disabled (which is what I think you are looking for) Can you confirm if you are able to actually check the checkboxes or not?
Unfortunately you can not disable the checkbox directly.
If this is what you want then you have a couple of options, you can either change the BackColor of the cell, which may be sufficient, however this will not actually change the colour of the checkbox itself.
You can also paint the control yourself, here is a microsoft guide to a similar tutorial.
Or you could create a disabled cell and replace the ones that you need with that. It's not too much work, especially when someone has already done it for you!
Upvotes: 0
Reputation: 1410
I had checked this in a small sample project and this worked for me:
// Loop through all the rows of your grid
foreach (DataGridViewRow row in this.dgvMailPreferences.Rows)
{
// Loop through all the cells of the row
foreach (DataGridViewCell cell in row.Cells)
{
// Check if the cell type is CheckBoxCell
// If not, check the next cell
if (!(cell is DataGridViewCheckBoxCell)) continue;
// Set the specific cell to read only, if the cell is not checked
cell.ReadOnly = !Convert.ToBoolean(cell.Value);
}
}
Further you can add an event to track cell changes to activate read only for clicked cells:
private void dgvMailPreferences_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (!(e.RowIndex >= 0 && e.ColumnIndex >= 0)) return;
DataGridViewCell cell = ((DataGridView)sender).Rows[e.RowIndex].Cells[e.ColumnIndex];
if (!(cell is DataGridViewCheckBoxCell)) return;
cell.ReadOnly = !System.Convert.ToBoolean(cell.Value);
}
(Fires after a change was done and the cell was left.)
You can build a sample project with the fiddle from Ivan Stoev at Dotnetfiddle
using System;
using System.Collections.Generic;
using System.Data;
using System.Windows.Forms;
namespace Samples
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var form = new Form();
var dgv = new DataGridView { Dock = DockStyle.Fill, Parent = form };
form.Load += (sender, e) =>
{
var dt = GetData();
dgv.DataSource = dt;
dgv.Columns["Mail Preference Description"].Width = 250;
dgv.Columns["Post"].Width = 50;
dgv.Columns["SMS"].Width = 50;
dgv.Columns["Email"].Width = 50;
dgv.Columns["Telephone"].Width = 75;
dgv.Columns["SEQ_ID"].Visible = false;
dgv.Columns["MAIL_PREFERENCE_ID"].Visible = false;
foreach (DataGridViewRow row in dgv.Rows)
{
foreach (DataGridViewCell cell in row.Cells)
{
if (cell.Value is bool && (bool)cell.Value == false)
cell.ReadOnly = true;
}
}
};
Application.Run(form);
}
static DataTable GetData()
{
var dt = new DataTable();
dt.Columns.Add("SEQ_ID", typeof(int)); // SEQ_ID
dt.Columns.Add("MAIL_PREFERENCE_ID", typeof(string)); // MAIL_PREFERENCE_ID
dt.Columns.Add("Mail Preference Description", typeof(string)); // MAIL_PREFERENCE_DESC
dt.Columns.Add("Post", typeof(bool)); // POST
dt.Columns.Add("SMS", typeof(bool)); // SMS
dt.Columns.Add("Email", typeof(bool)); // EMAIL
dt.Columns.Add("Telephone", typeof(bool)); // TELEPHONE
dt.Rows.Add(1, "1", "Membership", true, true, true, true);
dt.Rows.Add(2, "2", "Monthly Newsletter", false, false, true, false);
dt.Rows.Add(3, "3", "Mothhly Technical Briefing", false, false, true, false);
dt.Rows.Add(4, "4", "Magazine", false, false, true, false);
dt.Rows.Add(5, "5", "Branch Mailings", false, true, true, false);
dt.Rows.Add(6, "6", "Events", true, true, true, true);
dt.Rows.Add(7, "7", "Qualifications", true, true, true, true);
dt.Rows.Add(8, "8", "Training", true, true, true, true);
dt.Rows.Add(9, "9", "Recruitment", true, true, true, true);
dt.Rows.Add(10, "A", "General", true, true, true, true);
return dt;
}
}
}
Upvotes: 5
Reputation:
Try this
((DataGridViewCheckBoxCell)Rows[Index].Cells["colName"]).ReadOnly = true;
Hopefully it will work for you.
Upvotes: 1
Reputation: 247561
From my understanding, when populating, if the initial value of the checkbox is false then it should be read only.
Try setting the read only value using the following
// not setting the datagridview cell to readonly
foreach (DataGridViewRow row in dgvMailPreferences.Rows) {
foreach (DataGridViewCell cell in row.Cells) {
if (cell is DataGridViewCheckBoxCell) {
DataGridViewCheckBoxCell checkBoxCell = cell as DataGridViewCheckBoxCell;
//What is the initial value in the checkbox
bool isChecked = checkBoxCell.Value as bool;
//set to read only if not checked
checkBoxCell.ReadOnly = !isChecked;
}
}
}
Upvotes: 0