The first problem you will have is where to put the plus-sign as if it is on a hidden column you're not going to be able to see it to unhide the column!
So I've marked the hidden columns in my example below by putting a plus-sign on the header text of the column immediately to the left of a hidden column (note this means you cannot hide the first column [0]).
I've chosen to use a Context menu to control the Hide/Unhide as I wouldn't want columns appearing and disappearing just because the User clicked on the DGV.
The problem with this is determining which column the user right-clicked on to show the menu - this information is not available in
EventArgs
. I got around this by having a variable on the form
private int dgvCol = -1;
which I set whenever the user clicks within the DGV
private void dataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
dgvCol = e.ColumnIndex;
}
I then put a contextMenuStrip onto the form with 2 items "Hide Column" and "Unhide Columns" (note the plural) and set the
ContextMenuStrip
property of the DGV to that menu strip control.
You then need to wire up some events to handle those menu items..
private void hideColumnToolStripMenuItem_Click(object sender, EventArgs e)
{
...
}
private void unhideColumnsToolStripMenuItem_Click(object sender, EventArgs e)
{
...
}
I also decided to present the user with a list of hidden columns as a sub-menu to "Unhide Columns" which I build dynamically each time a column is hidden or unhidden.
Here's my full code, including a button just to set up some test data. It's not production strength (i.e. it still needs some work) but it should get you going. Note the alternatives offered (commented out) in
unhideColumnsToolStripMenuItem_Click
namespace DemoCollapseColumns
{
public partial class DGVCollapseColumns : Form
{
private int dgvCol = -1;
private void dataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
dgvCol = e.ColumnIndex;
}
private void hideColumnToolStripMenuItem_Click(object sender, EventArgs e)
{
if (dgvCol > 0)
hideColumn(dgvCol);
else
MessageBox.Show("Cannot hide the first column");
}
private void hideColumn(int colIndex)
{
dataGridView1.Columns[colIndex].Visible = false;
if (!dataGridView1.Columns[colIndex - 1].HeaderText.EndsWith("+"))
dataGridView1.Columns[colIndex - 1].HeaderText += "+";
SetUpUnhideSubMenu();
}
private void SetUpUnhideSubMenu()
{
ToolStripMenuItem ti = (contextMenuStrip1.Items["unhideColumnsToolStripMenuItem"] as ToolStripMenuItem);
ti.DropDownItems.Clear();
foreach (DataGridViewColumn c in dataGridView1.Columns)
{
if (!c.Visible)
{
ToolStripItem ti1 = ti.DropDownItems.Add(c.HeaderText, null, new EventHandler(UnHideMenu_ItemClicked));
ti1.Tag = c.Name;
}
}
}
private void unhideColumnsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (dataGridView1.Columns[dgvCol].HeaderText.EndsWith("+"))
{
while (dataGridView1.Columns[dgvCol].HeaderText.EndsWith("+"))
{
UnhideColumn(dgvCol + 1);
dgvCol += 1;
}
}
}
private void UnHideMenu_ItemClicked(object sender, EventArgs e)
{
var nam = ((ToolStripMenuItem)sender).Tag.ToString();
if (nam.EndsWith("+"))
nam = nam.Remove(nam.Length - 1, 1);
Console.WriteLine("sub menu clicked {0} : {1}", ((ToolStripMenuItem)sender).Text, nam);
UnhideColumn(dataGridView1.Columns[nam].Index);
}
private void UnhideColumn(int colIndex)
{
dataGridView1.Columns[colIndex].Visible = true;
dataGridView1.Columns[colIndex -1].HeaderText = dataGridView1.Columns[colIndex -1].HeaderText.Remove(dataGridView1.Columns[colIndex-1].HeaderText.Length - 1, 1);
SetUpUnhideSubMenu();
}
private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (dataGridView1.Columns[e.ColumnIndex].HeaderText.EndsWith("+"))
unhideColumnsToolStripMenuItem_Click(sender, (EventArgs)e);
}
public DGVCollapseColumns()
{
InitializeComponent();
}
private void SetupTest_Click(object sender, EventArgs e)
{
DataTable dt;
dt = new DataTable();
for (var i = 0; i < 11; i++)
{
dt.Columns.Add("Column " + i.ToString(), typeof(char));
}
for (var j = 0; j < 10; j++)
{
var dr = dt.NewRow();
dr.ItemArray = new object[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J','K' };
dt.Rows.Add(dr);
}
dataGridView1.DataSource = dt;
for (var k = 3; k < 6; k++)
hideColumn(k);
for (var k = 8; k < 10; k++)
hideColumn(k);
}
}
}