views:

1584

answers:

2

I edit data in a DataTable which is bound to a DataGridView. When a new column is created in the DataTable a new column is generated in the view.

Ordinarily I would set the view column properties in a DataGridView_ColumnAdded event, however the default for the columns at present is to add a view column with SortMode set to Automatic which is incompatible with the DataGridView ColumnHeaderSelect property and causes an error before the column added event can fire.

I presume I get around this by defining a 'template' column for newly generated columns - but how?

A: 

Interesting - I've done a lot with DataGridView and I haven't seen this. Perhaps the pragmatic option might be to build the columns manually? Probably not what you want to hear...

Marc Gravell
What do you mean by manually - in the designer or programmatically? I am trying not to use the designer since the data I'm reflecting is for use with arbitrary sized data sets of doubles and so the number of columns changes a lot.
Brendan
Programatically - by looping over the view columns.
Marc Gravell
+1  A: 

OK, time to hack it:

To demonstrate, here's a little app:

 public partial class Form1 : Form
    {
        DataTable table = new DataTable();
        public Form1()
        {
            InitializeComponent();
            this.dataGridView1.SelectionMode = DataGridViewSelectionMode.ColumnHeaderSelect;
            this.dataGridView1.ColumnAdded += new DataGridViewColumnEventHandler(dataGridView1_ColumnAdded);
        }

        void dataGridView1_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
        {
            Console.WriteLine("Column added");
            e.Column.SortMode = DataGridViewColumnSortMode.NotSortable;
        }

        private void button1_Click(object sender, EventArgs e)
        {

            table.Columns.Add("Name");
            table.Columns.Add("Age", typeof(int));

            table.Rows.Add("John", 27);
            this.FlipSelectionMode();
            this.dataGridView1.DataSource = table;
            this.FlipSelectionMode();

        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.FlipSelectionMode();
            table.Columns.Add("Height",typeof(int));
            table.Rows[0]["Height"] = 60;
            this.FlipSelectionMode();
        }

        private void FlipSelectionMode()
        {
            this.dataGridView1.SelectionMode = this.dataGridView1.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect ? DataGridViewSelectionMode.CellSelect : DataGridViewSelectionMode.ColumnHeaderSelect;
        }
    }

Basically, at first I set the DataGridView selection mode to ColumnHeaderSelect. On the button1 click, I add stuff to the datatable, and then bind it to the DataGridView. The trick is, that I call a method called FlipSelectionMode() before and after I bind the DGV. What this does, is if it's in columnheaderselect mode it flips it to cell select and vice versa. That enables the column to be added. Then, in the column added event, I set the columns sort property to Programmatic, otherwise, you won't be able to add another column. To demonstrate that, on the button2 click, it just adds another column, again while flipping the selection mode before and after.

I agree, this is a total hack, but the DGV is funky. I've had many many issues with it, and I almost always have to hack around stuff.

BFree
OK this is hackish but does work, +1
Brendan