Question

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;
}
Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top