4

I have seen a lot of posts on SO about weird behaviour of Columns and their visibility in particular when refreshing the grid and dynamically building the columns in the list, but haven't found a satisfactory solution.

After some digging I am almost certain this issue is due to the use of the DataGridView.Columns.Clear() method.

So far I haven't been able to work out why but removing the Clear() method when I dynamically build my DataGridView Columns stops hidden columns from appearing, but I don't understand why this would have any affect? Surely if you clear the Columns collection and use DataGridView.Columns.Add() to start adding new ones, code like;

dataGridView1.Columns.Clear(); // This is the offending method!!

dataGridView1.AutoGenerateColumns = false;
dataGridView1.ShowEditingIcon = false;
dataGridView1.RowHeadersVisible = false;

DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn();
col.DataPropertyName = "ID";
col.HeaderText = "ID";
col.Visible = false; // Notice the visibility of this column...
dataGridView1.Columns.Add(col);

... // Code is repeated for other columns in the collection

I can't see anything wrong with but if dataGridView1.Columns.Clear(); is included at the beginning my hidden column becomes visible, surely this is a bug?

Community
  • 1
  • 1
user692942
  • 16,398
  • 7
  • 76
  • 175
  • did you try dataGridView1.Invalidate() after adding the columns? – mihail Nov 19 '12 at 16:08
  • I did try that a long with `Refresh()` which is more or less the same thing. Behaves the same way... – user692942 Nov 19 '12 at 16:20
  • The only way I have managed to get around it is to stop dynamically rebuilding my column list which is not ideal (just loading my column creation method once at form load), as I want to show different results with different criteria. – user692942 Nov 19 '12 at 16:23
  • Have you tried some thing like an empty datatable to your datagridview some thing like `DataTable dtEmpty=new DataTable(); dataGridView1.DataSource = dtEmpty;` or simply `dataGridView1.DataSource = null`; – Developer Nov 20 '12 at 09:38
  • I have tried setting `dataGridView1.DataSource = null;` but as I'm not using `dataGridView1.AutoGenerateColumns = true;` this has no affect. Plus for reference I'm using Entity Framework with Repository pattern for my data. – user692942 Nov 20 '12 at 10:14
  • 1
    I love how this got down-voted, I provided all the information I could and tried to make the question as clear as possible. A bit of feedback as to what I could have done better would be nice. – user692942 Jan 26 '16 at 14:25

2 Answers2

3

I was able to reproduce the issue. The Clear method call is just fine, you can remove columns one by one and the issue still persists. The "offending" call is surprisingly Add:

col.Visible = false; // Notice the visibility of this column...
if (col.Visible)
{
   // Just to be sure. Never get here.
}
dataGridView1.Columns.Add(col);
if (col.Visible)
{
   // Surprise! We are here.
}

Why this behavior occurs?

It's definitely a bug. The issue is happening only and only if all the following conditions are met:

  1. DataGridView is in bound mode, i.e. has DataSource set. The data source type doesn't matter.
  2. Columns collection is empty
  3. Add method is called with a column having Visible = false

In this case the code hits an internal class DataGridViewDataConnection method MatchCurrencyManagerPosition. Take a look at the source code, especially the

// Treat case where columnIndex == -1. We change the visibility of the first column.

comment and the code block after that comment.

How to avoid it

To recap, this is happening only in data bound mode and only for the first added column if it is set to be hidden.

So there are a couple ways to fix that:

  1. Make sure the grid is not in bound mode when repopulating columns

    var dataSource = dataGridView.DataSource;
    dataGridView.DataSource = null;
    // Repopulate columns
    //...
    dataGridView.DataSource = dataSource;
    
  2. Don't use Add method. Create all columns and keep them in either variables or temporary list, and at the end use the AddRange method which has no such effect.

  3. Do not set Visible = false in advance. Create and add all the columns, then hide the desired ones.

user692942
  • 16,398
  • 7
  • 76
  • 175
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
0

This is due to the datatable's DefaultView being directly set as gridview's datasource.

We should set datasource property to DefaultView.ToTable() because whenever datatable is Cleared or Reset, then it clears metadata and hence loses the visibility information of grid.

Now this is really unidentified why reseting datatable information affects DataGridViewColumn's visibility.

fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • Thanks, I'll certainly have a look and see if this helps. – user692942 Nov 07 '14 at 14:59
  • Coming back to this just because I'm going through my old questions and realised this doesn't help. Reason being the `.Clear()` is called before a rebuild my columns and explicitly set to `Visible = false` before adding it to the `Columns` collection so although the old meta data has gone I'm creating new meta data. – user692942 Jan 26 '16 at 14:31