Why do Columns not stay hidden after calling DataGridView.Columns.Clear()?
Asked Answered
D

2

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?

Dipsomania answered 19/11, 2012 at 12:48 Comment(6)
did you try dataGridView1.Invalidate() after adding the columns?Geothermal
I did try that a long with Refresh() which is more or less the same thing. Behaves the same way...Dipsomania
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.Dipsomania
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;Alithia
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.Dipsomania
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.Dipsomania
B
4

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.

Buchalter answered 3/7, 2016 at 9:7 Comment(0)
P
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.

Penile answered 7/11, 2014 at 14:13 Comment(2)
Thanks, I'll certainly have a look and see if this helps.Dipsomania
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.Dipsomania

© 2022 - 2024 — McMap. All rights reserved.