Related Posts
I bumped into a question on StackOverflow this evening that I felt might make a short post. The accompanying code is available at my Github repo.
The guy who posted observed that the standard .NET DataGridView
control provides a helpful little glyph next to the row which contains the active cell:
The original poster of the question was wondering how he might include a similar glyph to indicate the active column as well. My problem with that is that there already exists an option for an arrow-like glyph in a column header. Unfortunately, THAT glyph, by convention, tends to mean “Click here to sort on this column.”
That does not mean that the OP was off-base, though. I can think of many cases where it would be handy to have some sort of reference to the active column in addition to the active row.
Emphasize the Active Column with the DataGridViewColumn.HeaderCell.Style Property
One way to approach this is to simply cause the text in the header cell to be bold when the user navigates to a cell within that column. We can create a class which inherits from DataGridView
, and take advantage of the CellEnter
Event to cause this to happen:
In the following code, we have a member variable which holds a reference to the last active column. In our constructor, we initialize this column object so that when the control is instantiated, the reference is not null
.
We also add an event handler to catch the CellEnter
event locally. When this event fires, the handler (dgvControl_CellEnter
) catches it, and makes a call to our final method, OnColumnFocus
. This method accepts a column index as a parameter, and uses the index to identify the new active column. From there, we can use the HeaderCell.Style
property to set the font to “bold
” for this particular column.
In our constructor, note that we have to make an initial call to the OnColumnFocus
method, so that the default starting column will be highlighted when the control is displayed at first. However, we have to check to see if there are actually any columns present first. This is because the Visual Studio Designer needs to be able to draw the empty control when we first place it on a form.
DataGridView: Cause the Active Column Header to Display Bold Text
class dgvControl : DataGridView
{
private DataGridViewColumn _currentColumn;
public dgvControl() : base()
{
this.CellEnter += new DataGridViewCellEventHandler(dgvControl_CellEnter);
_currentColumn = new DataGridViewColumn();
if (this.Columns.Count > 0)
{
this.OnColumnFocus(0);
}
}
void dgvControl_CellEnter(object sender, DataGridViewCellEventArgs e)
{
this.OnColumnFocus(e.ColumnIndex);
}
void OnColumnFocus(int ColumnIndex)
{
if (ColumnIndex != _currentColumn.Index)
{
Font selectedFont = new Font(this.Font, FontStyle.Bold);
var newColumn = this.Columns[ColumnIndex];
newColumn.HeaderCell.Style.Font = selectedFont;
_currentColumn.HeaderCell.Style.Font = this.Font;
_currentColumn = newColumn;
}
}
}
What If I Want More?
What if we want more than just bold text in the active header? Well, things get trickier. Manipulating the other properties of the HeaderCell
Style require setting EnableHeaderVisualStyles
to false
. This has the unfortunate side effect of flattening out the styling which some from the Windows 7 GUI styles. The slight gradient and color scheme are replaced by a much flatter header. While we could work around this by overriding the OnPaint
method (at least to a degree) and implementing our own painting scheme, the impact of the effect is not too disturbing.
For example, we could decide that in addition to bolding the text in the header, we will set the BackColor
to a slightly darker gray:
To do this, we need only add three lines of code. First off, in our constructor, we set the EnableHeaderVisualStyles
property to false
. Next, in our OnColumnFocus
method, we set the Style.BackColor
property of the new active column to a darker shade of gray, and restore the previous active column to the default (empty) backcolor:
DataGridView: Cause the Active Column Header to Display Bold Text with a Darker Back Color
class dgvControl : DataGridView
{
private DataGridViewColumn _currentColumn;
public dgvControl() : base()
{
this.EnableHeadersVisualStyles = false;
this.CellEnter += new DataGridViewCellEventHandler(dgvControl_CellEnter);
_currentColumn = new DataGridViewColumn();
if (this.Columns.Count > 0)
{
this.OnColumnFocus(0);
}
}
void dgvControl_CellEnter(object sender, DataGridViewCellEventArgs e)
{
this.OnColumnFocus(e.ColumnIndex);
}
void OnColumnFocus(int ColumnIndex)
{
if (ColumnIndex != _currentColumn.Index)
{
Font selectedFont = new Font(this.Font, FontStyle.Bold);
var newColumn = this.Columns[ColumnIndex];
newColumn.HeaderCell.Style.Font = selectedFont;
newColumn.HeaderCell.Style.BackColor = Color.LightGray;
_currentColumn.HeaderCell.Style.Font = this.Font;
_currentColumn.HeaderCell.Style.BackColor = Color.Empty;
_currentColumn = newColumn;
}
}
}
There are other options you might explore. In this post, we walked through some very basic ways to provide visual feedback to the user about their location within the DataGridView
control.
The source code for this post is available at my Github repo.