Have kind of a strange problem with a DataGridView
.
Its DataSource
bound to a list of objects with set; get;
It gets the data from this source as it should with all its boolean states for the checkboxes in the datagridview.
How ever, when I try to change checkboxes in the DataGridView
, it will only allow one checkbox to be checked at a time. a bit like radio buttons.
This is not the feature I am after, as I want to be able to check multiple numbers of the checkboxes and then maybe later save the changes that have been done to make it permanent.
Iv made this DataGridView
twice since I thought it might be some mysterious setting that might been included.
Any idea what might cause this?
Her comes some of the code.
Sets up the DGV in a regular form just for test
public partial class Form1 : Form
{
/// <summary>
///
/// </summary>
public struct TestObject
{
public string text { set; get; }
public bool cbOne { set; get; }
public bool cbTwo { set; get; }
}
public Form1()
{
InitializeComponent();
SetupDS();
}
private void SetupDS()
{
dataGridView1.DataSource = SetupDBdata();
}
private List<TestObject> SetupDBdata()
{
List<TestObject> list = new List<TestObject>();
for (int i = 0; i < 10; i++)
{
list.Add(new TestObject() { text = i.ToString() });
}
return list;
}
private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (dataGridView1.IsCurrentCellDirty)
{
dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
}
Design code
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.txt = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.cb1 = new System.Windows.Forms.DataGridViewCheckBoxColumn();
this.cb2 = new System.Windows.Forms.DataGridViewCheckBoxColumn();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
this.SuspendLayout();
//
// dataGridView1
//
this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.txt,
this.cb1,
this.cb2});
this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
this.dataGridView1.Location = new System.Drawing.Point(0, 0);
this.dataGridView1.Name = "dataGridView1";
this.dataGridView1.Size = new System.Drawing.Size(651, 390);
this.dataGridView1.TabIndex = 0;
this.dataGridView1.CurrentCellDirtyStateChanged += new System.EventHandler(this.dataGridView1_CurrentCellDirtyStateChanged);
//
// txt
//
this.txt.DataPropertyName = "text";
this.txt.HeaderText = "text";
this.txt.Name = "txt";
//
// cb1
//
this.cb1.DataPropertyName = "cbOne";
this.cb1.HeaderText = "cb1";
this.cb1.Name = "cb1";
//
// cb2
//
this.cb2.DataPropertyName = "cbTwo";
this.cb2.HeaderText = "cb2";
this.cb2.Name = "cb2";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(651, 390);
this.Controls.Add(this.dataGridView1);
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.DataGridView dataGridView1;
private System.Windows.Forms.DataGridViewTextBoxColumn txt;
private System.Windows.Forms.DataGridViewCheckBoxColumn cb1;
private System.Windows.Forms.DataGridViewCheckBoxColumn cb2;
}
Your problem is you use a struct
as the underlying databound item. All the modification you've done on the records will be applied on the copy of the underlying item. You should use a class instead:
public class TestObject
{
//....
}
The underlying mechanism will fetch the item via the indexer of your List
, you know the indexer
of your List<TestObject>
can be like this:
public TestObject this[int index] {
get { return someValue;}
set { ... }
}
the someValue
will be your struct
instance and you know that way the return value is just a copy of the actual struct. So all the changes on the copy won't reflect to the actual struct. A simple test with your list can be done with this code:
yourList[0].text = "???"; //<--- error saying Cannot modify the return value of ...
//because it is not a variable.
That error is notified by design, changing the data members of a copy would mean nothing, so just notify some error to prevent programmer from compiling useless code.