Click here to Skip to main content
15,867,704 members
Articles / Desktop Programming / Windows Forms
Article

A DataGridView Column Show/Hide Popup

Rate me:
Please Sign up or sign in to vote.
4.80/5 (56 votes)
23 Dec 2008CPOL1 min read 197.3K   9K   152   50
A class adding column show/hide capability to a DataGridView

Introduction

Many applications offer users a useful feature to show/hide columns of data. In Windows Forms, the control dedicated to show tabular data is DataGridView but there isn't a built-in column selection mechanism. I wrote the small class DataGridViewColumnSelector to fill this void.

Background

The <code>DataGridViewColumnSelector class is a new class and not a derivation of the DataGridView class. You don't need to change your DataGridView instances declarations. Simply create an instance of DataGridViewColumnSelector and attach a DataGridView instance to it. When the user right-clicks the cell origin, a pupup is shown, allowing to check/uncheck the columns to show.

The column list is implemented through a CheckedListBox and the popup effect is achieved by means of a ToolStripDropDown object to which a ToolStripControlHost object is added. The latter contains the CheckedListBox. Read the article, "How to: Wrap a Windows Forms Control with ToolStripControlHost", to get some background.

Here is the constructor code:

C#
// The constructor creates an instance of CheckedListBox and ToolStripDropDown.
// the CheckedListBox is hosted by ToolStripControlHost, which in turn is
// added to ToolStripDropDown.
public DataGridViewColumnSelector() {
	mCheckedListBox = new CheckedListBox();
	mCheckedListBox.CheckOnClick = true;
	mCheckedListBox.ItemCheck += 
		new ItemCheckEventHandler(mCheckedListBox_ItemCheck);

	ToolStripControlHost mControlHost = new ToolStripControlHost(mCheckedListBox);
	mControlHost.Padding = Padding.Empty;
	mControlHost.Margin = Padding.Empty;
	mControlHost.AutoSize = false;

	mPopup = new ToolStripDropDown();
	mPopup.Padding = Padding.Empty;
	mPopup.Items.Add(mControlHost);
}

When user right-clicks the cell origin, the mDataGridView_CellMouseClick is called. It clears and fills the CheckedListBox with columns header text. Then it shows the popup. In this way, the CheckedListBox items are always refreshed to reflect changes that occurred in DataGridView columns (column additions or name changes and so on).

C#
void mDataGridView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
	if (e.Button == MouseButtons.Right && e.RowIndex==-1 && e.ColumnIndex==-1) {
		mCheckedListBox.Items.Clear();
		foreach (DataGridViewColumn c in mDataGridView.Columns){
			mCheckedListBox.Items.Add(c.HeaderText, c.Visible);
		}
		int PreferredHeight = (mCheckedListBox.Items.Count * 16) + 7;
		mCheckedListBox.Height = (PreferredHeight < MaxHeight) ? 
					PreferredHeight : MaxHeight;
		mCheckedListBox.Width = this.Width;
		mPopup.Show(mDataGridView.PointToScreen(new Point (e.X,e.Y)));
	}
}

Finally, when user checks/unchecks a checkbox, the related column visibility is switched by mCheckedListBox_ItemCheck event handler.

C#
void mCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e){
	mDataGridView.Columns[e.Index].Visible = (e.NewValue == CheckState.Checked);
}

Using the Code

Copy the DataGridViewColumnSelector.cs file to your project. Change the namespace if you need.

You can pass the DataGridView instance directly as constructor parameter:

C#
new DataGridViewColumnSelector(dataGridView1);

Or you can create an instance and then attach a DataGridView using the DataGridView property:

C#
DataGridViewColumnSelector cs = new DataGridViewColumnSelector();
cs.DataGridView = dataGridView1;
cs.MaxHeight = 200;
cs.Width = 110;

Optionally use MaxHeight and Width properties to adjust the size of the popup.

History

  • 23rd December, 2008: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead
Italy Italy
I'm a graduate in Computer Science.
I work with Metatrader MQL4,MQL5 / C# / Asp.Net / Windows Forms / SQL Server / Access / VBA / HTML / CSS / Javascript / classic C/C++.


I also like writing songs and playing around with my band Diversamente Rossi.
This is the video of the song Un'altra estate from the album L'immobile disegno.



"Short code, good code"

Comments and Discussions

 
GeneralRe: Thank you for the great article. Pin
Vincenzo Rossi1-Sep-09 8:46
professionalVincenzo Rossi1-Sep-09 8:46 
GeneralRe: Thank you for the great article. Pin
Vincenzo Rossi1-Sep-09 8:57
professionalVincenzo Rossi1-Sep-09 8:57 
GeneralRe: Thank you for the great article. Pin
Fiwel1-Sep-09 9:10
Fiwel1-Sep-09 9:10 
QuestionIs there a VC++ version? Pin
occamRT1-Jul-09 6:55
occamRT1-Jul-09 6:55 
AnswerRe: Is there a VC++ version? Pin
Vincenzo Rossi11-Jul-09 3:35
professionalVincenzo Rossi11-Jul-09 3:35 
GeneralContext Menu Strip Problem Pin
kapil bhavsar22-Jun-09 4:11
kapil bhavsar22-Jun-09 4:11 
GeneralThanks a lot Pin
amir897627-May-09 0:58
amir897627-May-09 0:58 
NewsImplemented Indeterminate check status Pin
Deepak SHAW25-Feb-09 10:46
Deepak SHAW25-Feb-09 10:46 
just replace the class below : Any hidden column(s) of your datagridview would be disabled Shucks | :-\
------------------------------
class DataGridViewColumnSelector
{
// the DataGridView to which the DataGridViewColumnSelector is attached
private DataGridView mDataGridView = null;
// a CheckedListBox containing the column header text and checkboxes
private CheckedListBox mCheckedListBox;
// a ToolStripDropDown object used to show the popup
private ToolStripDropDown mPopup;

//Get information of all hidden columns of DataGridView
private string[] HiddenColumnName;

/// <summary>
/// The max height of the popup
/// </summary>
public int MaxHeight = 300;
/// <summary>
/// The width of the popup
/// </summary>
public int Width = 200;

/// <summary>
/// Gets or sets the DataGridView to which the DataGridViewColumnSelector is attached
/// </summary>
public DataGridView DataGridView
{
get { return mDataGridView; }
set
{
// If any, remove handler from current DataGridView
if (mDataGridView != null) mDataGridView.CellMouseClick -= new DataGridViewCellMouseEventHandler(mDataGridView_CellMouseClick);
// Set the new DataGridView
mDataGridView = value;
// Attach CellMouseClick handler to DataGridView
if (mDataGridView != null) mDataGridView.CellMouseClick += new DataGridViewCellMouseEventHandler(mDataGridView_CellMouseClick);
}
}

// When user right-clicks the cell origin, it clears and fill the CheckedListBox with
// columns header text. Then it shows the popup.
// In this way the CheckedListBox items are always refreshed to reflect changes occurred in
// DataGridView columns (column additions or name changes and so on).
void mDataGridView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{

if (e.Button == MouseButtons.Right && e.RowIndex == -1 && e.ColumnIndex == -1)
{
mCheckedListBox.Items.Clear();
foreach (DataGridViewColumn c in mDataGridView.Columns)
{
if(Array.IndexOf(HiddenColumnName,c.HeaderText) <0)
mCheckedListBox.Items.Add(c.HeaderText, c.Visible);
else
mCheckedListBox.Items.Add(c.HeaderText, CheckState.Indeterminate);
}
int PreferredHeight = (mCheckedListBox.Items.Count * 16) + 7;
mCheckedListBox.Height = (PreferredHeight < MaxHeight) ? PreferredHeight : MaxHeight;
mCheckedListBox.Width = this.Width;
mPopup.Show(mDataGridView.PointToScreen(new Point(e.X, e.Y)));
}
}

// The constructor creates an instance of CheckedListBox and ToolStripDropDown.
// the CheckedListBox is hosted by ToolStripControlHost, which in turn is
// added to ToolStripDropDown.
public DataGridViewColumnSelector()
{
mCheckedListBox = new CheckedListBox();
mCheckedListBox.CheckOnClick = true;
mCheckedListBox.ItemCheck += new ItemCheckEventHandler(mCheckedListBox_ItemCheck);

ToolStripControlHost mControlHost = new ToolStripControlHost(mCheckedListBox);
mControlHost.Padding = Padding.Empty;
mControlHost.Margin = Padding.Empty;
mControlHost.AutoSize = false;

mPopup = new ToolStripDropDown();
mPopup.Padding = Padding.Empty;
mPopup.Items.Add(mControlHost);
}

public DataGridViewColumnSelector(DataGridView dgv) : this()
{
int i = 0;
this.DataGridView = dgv;
HiddenColumnName = new string[dgv.ColumnCount];
foreach (DataGridViewColumn c in dgv.Columns)
{
if (c.Visible == false)
HiddenColumnName[i] = c.HeaderText;
i++;
}
}

// When user checks / unchecks a checkbox, the related column visibility is
// switched.
void mCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
if (e.CurrentValue == CheckState.Indeterminate)
e.NewValue = e.CurrentValue; // no change if CheckState is Indeterminate
else
mDataGridView.Columns[e.Index].Visible = (e.NewValue == CheckState.Checked);
}
------------------------------
GeneralJust what I want Pin
RubyPdf10-Feb-09 3:20
RubyPdf10-Feb-09 3:20 
GeneralRe: Just what I want Pin
Vincenzo Rossi10-Feb-09 9:55
professionalVincenzo Rossi10-Feb-09 9:55 
Generalgreat code Pin
Donsw5-Jan-09 14:06
Donsw5-Jan-09 14:06 
GeneralCool Indeed Pin
AngleV29-Dec-08 8:30
AngleV29-Dec-08 8:30 
GeneralRe: Cool Indeed Pin
Vincenzo Rossi29-Dec-08 12:59
professionalVincenzo Rossi29-Dec-08 12:59 
GeneralWay cool, Pin
BGaddis23-Dec-08 6:53
BGaddis23-Dec-08 6:53 
GeneralRe: Way cool, Pin
Vincenzo Rossi23-Dec-08 7:14
professionalVincenzo Rossi23-Dec-08 7:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.