Click here to Skip to main content
Click here to Skip to main content

A DataGridView Column Show/Hide Popup

By , 23 Dec 2008
 

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 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:

// 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).

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.

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:

new DataGridViewColumnSelector(dataGridView1);

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

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)

About the Author

Vincenzo Rossi
Software Developer (Senior)
Italy Italy
I'm a graduate in Computer Science.
I work with C++, Visual Basic 6, C#, asp, asp.Net, Windows Forms, SQL Server, Access, Flash.
 


"Short code, good code"



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5 PinmemberAli_IND7-Jun-13 21:43 
Very useful
QuestionThank you very much! Pinmembermiteleda9-Nov-12 15:23 
Thank you very much!
QuestionSave column selection PinmemberMJhaa5-Nov-12 8:57 
hi,
 
Is there a way i can save the column selection so that i don't have to redo the selection for show/hide columns everytime i launch the application.
 
thanks, Mini
GeneralMy vote of 5 PinmemberMJhaa31-Oct-12 7:38 
i needed it in vb.net, after converting the code to vb, it works like charm.. thanks so much Smile | :)
GeneralMy vote of 5 PinmemberVincent Paukgyi24-Sep-12 22:22 
Very useful and neat
QuestionGood Job PinmemberAliasgar M, Maimoon6-Sep-12 23:54 
Thanks Boss, I was hunting around the web for this type of functionality, at last found in your code.
 
Thanks
GeneralMy vote of 5 PinmemberProEnggSoft29-Feb-12 19:21 
Good article
Questionthanks your code! Pinmembercaohit18-Feb-12 3:15 
thanks your code!
QuestionWhat If I have Columns That Must Stay Hidden? Pinmemberpointeman130-Dec-11 3:01 
I noticed this project works great if you want to expose ALL columns. Problems arise when you don't want the hidden ID column to show. Also how do I handle checkBox and image columns. Help?
QuestionIt does not work when the datagridview has a contextmenu object Pinmemberwuhuacong20-Aug-11 17:14 
It does not work when the datagridview has a contextmenu object.
Is there a solution to solve the problem?
GeneralMy vote of 5 PinmemberMember 79087416-Jul-11 9:14 
Very helpful! Thanks
GeneralThanks for your info.. PingroupYZK29-Mar-11 22:32 
Thanks for your info..
GeneralThanks PingroupYZK29-Mar-11 22:30 
Thanks for your information........
GeneralMy vote of 5 Pinmembersnake2k3y@rambler.ru18-Mar-11 20:57 
Thanks a lot, i'll use it in my project!
GeneralMy vote of 5 Pinmemberbtaz12523-Feb-11 1:18 
It's useful. Thanks so much.
GeneralMy vote of 5 PinmemberWasiq Amjad Bhamla29-Jan-11 9:27 
very nice article. perfect 5 from me.
GeneralMy vote of 5 Pinmembersajadjamalian27-Jan-11 20:57 
very good.
GeneralMy vote of 5 PinmemberJunfengGuo5-Dec-10 14:24 
great job, a very good implement of datagridview, thanks for sharing
GeneralMy vote of 5 PinmemberMember 159022321-Oct-10 16:45 
Amazing Code Hello Vin, it's perfect class code, do alot of thing with little thing. Normally I use konvensional checklistbox at left of datagridview that reduce the datagridview space. now change it with yours and also combine with your filterPopUp column article in http://www.codeproject.com/KB/grid/DataGridViewFilterPopup.aspx, I am very happy with it, your code very usefull, thanks alots for amazing code [Razak]
GeneralThanks a lot PinmemberSunvory29-Dec-09 15:09 
Smile | :)
GeneralPerfect!! Pinmembermiyayo6-Nov-09 3:48 
Thanks for this code!!
GeneralGreat Article PinmemberManvendrak21-Oct-09 17:03 
It just the way i wanted.
Author made this code look so simple.
Thanks Rossi. Poke tongue | ;-P
GeneralRe: Great Article PinmemberVincenzo Rossi22-Oct-09 8:48 
GeneralThank you for the great article. [modified] PinmemberFiwel31-Aug-09 19:33 
You helped me a great deal.
I hope you do not mind, I extended your article:
A DataGridView Column Show/Hide Popup - Menu Style
 
I mentioned your name and original source.
Thank you again, and all the best.
 
modified on Tuesday, September 1, 2009 2:10 AM

GeneralRe: Thank you for the great article. PinmemberFiwel31-Aug-09 19:34 
GeneralRe: Thank you for the great article. PinmemberVincenzo Rossi1-Sep-09 8:46 
GeneralRe: Thank you for the great article. PinmemberVincenzo Rossi1-Sep-09 8:57 
GeneralRe: Thank you for the great article. PinmemberFiwel1-Sep-09 9:10 
QuestionIs there a VC++ version? PinmemberoccamRT1-Jul-09 6:55 
Is there a VC++ version?
AnswerRe: Is there a VC++ version? PinmemberVincenzo Rossi11-Jul-09 3:35 
GeneralContext Menu Strip Problem Pinmemberkapil bhavsar22-Jun-09 4:11 
Thanx for the nice control.
 
My problem is i want to use ContextMenuStrip also with DGV but this doesnt let the ColumnSelector Popup to show. Any Solution to this will be very helpful.
 
Thanks Again.
GeneralThanks a lot Pinmemberamir897627-May-09 0:58 
Thanks a lot
NewsImplemented Indeterminate check status PinmemberMember 38912925-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 PinmemberSteed Soft10-Feb-09 3:20 
I used it in my little project, thanks.
 

GeneralRe: Just what I want PinmemberVincenzo Rossi10-Feb-09 9:55 
Generalgreat code PinmemberDonsw5-Jan-09 14:06 
This was something I had been toying with and could not find the time to explore it. Thanks for doing it. I will see if it fits with what I am doing. Great work. Smile | :)
GeneralCool Indeed PinmemberAngleV29-Dec-08 8:30 
Just what i need it
you got my 5 for this
GeneralRe: Cool Indeed PinmemberVincenzo Rossi29-Dec-08 12:59 
GeneralWay cool, PinmemberBGaddis23-Dec-08 6:53 
Been looking to do this for some time, just never did it. Now I have no need to thanks to you.
 
Adding manpower to a late software project only makes it later.

GeneralRe: Way cool, PinmemberVincenzo Rossi23-Dec-08 7:14 

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130617.1 | Last Updated 23 Dec 2008
Article Copyright 2008 by Vincenzo Rossi
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid