Two Row Headers in DataGridView

A

anbaesivam

In my application, I need DataGridView with two rows of header. The first
header is for the Column names and second header is for selecting the default
value for that column.

Is it possible with C# .NET?. If possible please send me the sample code.

Thanks in advance.
 
C

Colbert Zhou [MSFT]

Hello Anbaesivam,

Thanks for using Microsoft Newsgroup Support Service, my name is Colbert
Zhou [MSFT] and I will be working on this issue with you.

Firstly, please let me make sure I understand your issue correctly. Now, we
are trying to create two rows of header in the DataGridView, right? Please
correct me if I have misunderstood your issue.

Based on my knowledge, the Windows Form DataGridView does not support
multiple rows of headers by default. The DataGridView Program Manager Mark
has confirmed this in the following forum discussion:

http://social.msdn.microsoft.com/Forums/en-US/winformsdatacontrols/thread/49
e62b5a-51a2-4daf-b77b-8491d0d19b24/

If we really want this, we have to draw the header by ourselves. The
followings are codes work fine in my side. Would you mind giving it a try
and let me know if this resolves your issue?

private void Form1_Load(object sender, EventArgs e)
{
this.dataGridView1.Columns.Add("Column1", "My Column 1");
this.dataGridView1.Columns.Add("Column2", "My Column 2");

for (int j = 0; j < this.dataGridView1.ColumnCount; j++)
{
this.dataGridView1.Columns[j].Width = 120;
}

this.dataGridView1.ColumnHeadersHeightSizeMode =
DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
this.dataGridView1.ColumnHeadersHeight =
this.dataGridView1.ColumnHeadersHeight * 2;
this.dataGridView1.ColumnHeadersDefaultCellStyle.Alignment =
DataGridViewContentAlignment.TopCenter;
this.dataGridView1.Paint += new
PaintEventHandler(dataGridView1_Paint);
}

void dataGridView1_Paint(object sender, PaintEventArgs e)
{
string[] defaultValues = { "Default Value 1", "Default Value 2"
};

for (int j = 0; j < 2; )
{
Rectangle r1 =
this.dataGridView1.GetCellDisplayRectangle(j, -1, true); //get the column
header cell
r1.X += 1;
r1.Y = r1.Height / 2 + 1;
r1.Width -= 2;
r1.Height = r1.Height / 2 - 2;
e.Graphics.FillRectangle(new
SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.BackColor), r1);

StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
e.Graphics.DrawString(defaultValues[j],
this.dataGridView1.ColumnHeadersDefaultCellStyle.Font,
new
SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.ForeColor),
r1,
format);
j++;
}
}


Best regards,
Colbert Zhou ([email protected], remove 'online.')
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://support.microsoft.com/select/default.aspx?target=assistance&ln=en-us.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
A

anbaesivam

Thanks for your solution.

I have one more query.

In the second row header is it possible to have combo box, such that the
user can select the default value from a set of values?

Colbert Zhou said:
Hello Anbaesivam,

Thanks for using Microsoft Newsgroup Support Service, my name is Colbert
Zhou [MSFT] and I will be working on this issue with you.

Firstly, please let me make sure I understand your issue correctly. Now, we
are trying to create two rows of header in the DataGridView, right? Please
correct me if I have misunderstood your issue.

Based on my knowledge, the Windows Form DataGridView does not support
multiple rows of headers by default. The DataGridView Program Manager Mark
has confirmed this in the following forum discussion:

http://social.msdn.microsoft.com/Forums/en-US/winformsdatacontrols/thread/49
e62b5a-51a2-4daf-b77b-8491d0d19b24/

If we really want this, we have to draw the header by ourselves. The
followings are codes work fine in my side. Would you mind giving it a try
and let me know if this resolves your issue?

private void Form1_Load(object sender, EventArgs e)
{
this.dataGridView1.Columns.Add("Column1", "My Column 1");
this.dataGridView1.Columns.Add("Column2", "My Column 2");

for (int j = 0; j < this.dataGridView1.ColumnCount; j++)
{
this.dataGridView1.Columns[j].Width = 120;
}

this.dataGridView1.ColumnHeadersHeightSizeMode =
DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
this.dataGridView1.ColumnHeadersHeight =
this.dataGridView1.ColumnHeadersHeight * 2;
this.dataGridView1.ColumnHeadersDefaultCellStyle.Alignment =
DataGridViewContentAlignment.TopCenter;
this.dataGridView1.Paint += new
PaintEventHandler(dataGridView1_Paint);
}

void dataGridView1_Paint(object sender, PaintEventArgs e)
{
string[] defaultValues = { "Default Value 1", "Default Value 2"
};

for (int j = 0; j < 2; )
{
Rectangle r1 =
this.dataGridView1.GetCellDisplayRectangle(j, -1, true); //get the column
header cell
r1.X += 1;
r1.Y = r1.Height / 2 + 1;
r1.Width -= 2;
r1.Height = r1.Height / 2 - 2;
e.Graphics.FillRectangle(new
SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.BackColor), r1);

StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
e.Graphics.DrawString(defaultValues[j],
this.dataGridView1.ColumnHeadersDefaultCellStyle.Font,
new
SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.ForeColor),
r1,
format);
j++;
}
}


Best regards,
Colbert Zhou ([email protected], remove 'online.')
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://support.microsoft.com/select/default.aspx?target=assistance&ln=en-us.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
C

Colbert Zhou [MSFT]

Hello Anbaesivam,

Yes, we can just remove the drawing string codes in the Paint event handle,
and add creating combobox codes in the Form.Load event handle. In the
DataGridView.Invalidated event handle, we need to reset the ComboBox's size
and location.

These codes work fine in my side,
Dictionary<String, ComboBox> headerComboBox = new
Dictionary<string, ComboBox>();

private void Form1_Load(object sender, EventArgs e)
{
this.dataGridView1.Columns.Add("Column1", "My Column 1");
this.dataGridView1.Columns.Add("Column2", "My Column 2");

this.dataGridView1.ColumnHeadersHeightSizeMode =
DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
this.dataGridView1.ColumnHeadersHeight =
this.dataGridView1.ColumnHeadersHeight * 2;
this.dataGridView1.ColumnHeadersDefaultCellStyle.Alignment =
DataGridViewContentAlignment.TopCenter;
this.dataGridView1.Paint += new
PaintEventHandler(dataGridView1_Paint);
this.dataGridView1.Invalidated += new
InvalidateEventHandler(dataGridView1_Invalidated);

for (int j = 0; j < 2; j++)
{
ComboBox cbb = new ComboBox();
cbb.Items.Add("Default Value 1");
cbb.Items.Add("Default Value 2");
cbb.Items.Add("Default Value 3");
headerComboBox.Add("ComboBox" + j.ToString(), cbb);
Rectangle r1 =
this.dataGridView1.GetCellDisplayRectangle(j, -1, true);
r1.X += 1;
r1.Y = r1.Height / 2 + 1;
r1.Width -= 2;
r1.Height = r1.Height / 2 - 2;

this.dataGridView1.Controls.Add(cbb);
cbb.Location = r1.Location;
cbb.Width = r1.Width;
cbb.Height = r1.Height;
}

for (int j = 0; j < this.dataGridView1.ColumnCount; j++)
{
this.dataGridView1.Columns[j].Width = 120;
}
}

void dataGridView1_Paint(object sender, PaintEventArgs e)
{
for (int j = 0; j < 2; )
{
Rectangle r1 =
this.dataGridView1.GetCellDisplayRectangle(j, -1, true);
r1.X += 1;
r1.Y = r1.Height / 2 + 1;
r1.Width -= 2;
r1.Height = r1.Height / 2 - 2;
e.Graphics.FillRectangle(new
SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.BackColor), r1);

j++;
}
}

void dataGridView1_Invalidated(object sender, InvalidateEventArgs e)
{
for (int j = 0; j < 2; )
{
Rectangle r1 =
this.dataGridView1.GetCellDisplayRectangle(j, -1, true);
r1.X += 1;
r1.Y = r1.Height / 2 + 1;
r1.Width -= 2;
r1.Height = r1.Height / 2 - 2;

ComboBox cbb = headerComboBox["ComboBox" + j.ToString()];

cbb.Location = r1.Location;
cbb.Width = r1.Width;
cbb.Height = r1.Height;
j++;
}
}

Any future questions or conerns, please feel free to let me know!

Best regards,
Colbert Zhou ([email protected], remove 'online.')
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.
 
A

anbaesivam

Thanks. The solution exactly suites my requirement.

I have one more requirement.

Is it possible to populate the value selected in the combobox(one in the
header) to all the cells in that column?.

Thanks a lot.



Colbert Zhou said:
Hello Anbaesivam,

Yes, we can just remove the drawing string codes in the Paint event handle,
and add creating combobox codes in the Form.Load event handle. In the
DataGridView.Invalidated event handle, we need to reset the ComboBox's size
and location.

These codes work fine in my side,
Dictionary<String, ComboBox> headerComboBox = new
Dictionary<string, ComboBox>();

private void Form1_Load(object sender, EventArgs e)
{
this.dataGridView1.Columns.Add("Column1", "My Column 1");
this.dataGridView1.Columns.Add("Column2", "My Column 2");

this.dataGridView1.ColumnHeadersHeightSizeMode =
DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
this.dataGridView1.ColumnHeadersHeight =
this.dataGridView1.ColumnHeadersHeight * 2;
this.dataGridView1.ColumnHeadersDefaultCellStyle.Alignment =
DataGridViewContentAlignment.TopCenter;
this.dataGridView1.Paint += new
PaintEventHandler(dataGridView1_Paint);
this.dataGridView1.Invalidated += new
InvalidateEventHandler(dataGridView1_Invalidated);

for (int j = 0; j < 2; j++)
{
ComboBox cbb = new ComboBox();
cbb.Items.Add("Default Value 1");
cbb.Items.Add("Default Value 2");
cbb.Items.Add("Default Value 3");
headerComboBox.Add("ComboBox" + j.ToString(), cbb);
Rectangle r1 =
this.dataGridView1.GetCellDisplayRectangle(j, -1, true);
r1.X += 1;
r1.Y = r1.Height / 2 + 1;
r1.Width -= 2;
r1.Height = r1.Height / 2 - 2;

this.dataGridView1.Controls.Add(cbb);
cbb.Location = r1.Location;
cbb.Width = r1.Width;
cbb.Height = r1.Height;
}

for (int j = 0; j < this.dataGridView1.ColumnCount; j++)
{
this.dataGridView1.Columns[j].Width = 120;
}
}

void dataGridView1_Paint(object sender, PaintEventArgs e)
{
for (int j = 0; j < 2; )
{
Rectangle r1 =
this.dataGridView1.GetCellDisplayRectangle(j, -1, true);
r1.X += 1;
r1.Y = r1.Height / 2 + 1;
r1.Width -= 2;
r1.Height = r1.Height / 2 - 2;
e.Graphics.FillRectangle(new
SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.BackColor), r1);

j++;
}
}

void dataGridView1_Invalidated(object sender, InvalidateEventArgs e)
{
for (int j = 0; j < 2; )
{
Rectangle r1 =
this.dataGridView1.GetCellDisplayRectangle(j, -1, true);
r1.X += 1;
r1.Y = r1.Height / 2 + 1;
r1.Width -= 2;
r1.Height = r1.Height / 2 - 2;

ComboBox cbb = headerComboBox["ComboBox" + j.ToString()];

cbb.Location = r1.Location;
cbb.Width = r1.Width;
cbb.Height = r1.Height;
j++;
}
}

Any future questions or conerns, please feel free to let me know!

Best regards,
Colbert Zhou ([email protected], remove 'online.')
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.
 
C

Colbert Zhou [MSFT]

Yes, we need to register the ComboBox's SelectedValueChanged event. In the
event handle, we populate the selected value to all cells in current column.

private void Form1_Load(object sender, EventArgs e)
{
this.dataGridView1.Columns.Add("Column1", "My Column 1");
this.dataGridView1.Columns.Add("Column2", "My Column 2");

this.dataGridView1.ColumnHeadersHeightSizeMode =
DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
this.dataGridView1.ColumnHeadersHeight =
this.dataGridView1.ColumnHeadersHeight * 2;
this.dataGridView1.ColumnHeadersDefaultCellStyle.Alignment =
DataGridViewContentAlignment.TopCenter;
this.dataGridView1.Paint += new
PaintEventHandler(dataGridView1_Paint);
this.dataGridView1.Invalidated += new
InvalidateEventHandler(dataGridView1_Invalidated);

for (int j = 0; j < 2; j++)
{
ComboBox cbb = new ComboBox();
cbb.Name = j.ToString();
cbb.Items.Add("Default Value 1");
cbb.Items.Add("Default Value 2");
cbb.Items.Add("Default Value 3");
cbb.SelectedValueChanged += new
EventHandler(cbb_SelectedValueChanged);
headerComboBox.Add("ComboBox" + j.ToString(), cbb);
Rectangle r1 =
this.dataGridView1.GetCellDisplayRectangle(j, -1, true);
r1.X += 1;
r1.Y = r1.Height / 2 + 1;
r1.Width -= 2;
r1.Height = r1.Height / 2 - 2;

this.dataGridView1.Controls.Add(cbb);
cbb.Location = r1.Location;
cbb.Width = r1.Width;
cbb.Height = r1.Height;
}

for (int j = 0; j < this.dataGridView1.ColumnCount; j++)
{
this.dataGridView1.Columns[j].Width = 120;
}
}

void cbb_SelectedValueChanged(object sender, EventArgs e)
{
Int32 index = Convert.ToInt32(((ComboBox)sender).Name);
foreach (DataGridViewRow r in this.dataGridView1.Rows)
{
if (r.Cells[index].Value == null)
{
r.Cells[index].Value = ((ComboBox)sender).Text;
}
}
}

Any future questions, please feel free to update this thread! Have a good
day!

Best regards,
Colbert Zhou ([email protected], remove 'online.')
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.
 
Joined
Feb 20, 2009
Messages
1
Reaction score
0
Hello,

I am wondering your article. What I need is that second column have distint number of columns. For Instance:

|Column 1|Column 2|
| 1 | 2 |1|2|3|4|5|

¿Do you understand me?

Thanks in advance.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top