I am using WPF DataGrid and I would like to allow the user to select an entire column by clicking on the column header. I currently have the SelectionUnit set to CellOrRowHeader because I want the same functionality for rows (which works great). Is there an easy way to also allow selection of columns by clicking the column header?
-
I recently had a same situation and after hours of search and finding absolutely nothing, finally implemented it with a mouse event and a loop! – Bizhan Jan 30 '12 at 14:15
-
I was thinking maybe it could be done by overriding the column header style to make it a button and then adding a click event on that button. I'd like to make it look just like the row header style but I'm new at styling. Maybe if I could figure out what the row header style looks like I can copy that and make adjustments to use for column header... – KrisTrip Jan 30 '12 at 14:23
-
by override if you mean classic overriding, then it's not the best solution when you have the great potentials of styling and templating in WPF. But your idea is correct and might work if you override the default Aero styles like this: http://stackoverflow.com/questions/643440/override-default-styling-in-wpf-textbox-based-on-presentationframework-aero however if you change the template of a control then the default styles might not work anymore. – Bizhan Jan 30 '12 at 22:22
3 Answers
You have many options. one is create your own Template for DataGrid's Header Style. Inside the DataTemplate tag you can change the template of the headers. (you can replace the Button with a TextBlock or anything you want.)
<DataGrid>
<DataGrid.ColumnHeaderStyle>
<Style TargetType="DataGridColumnHeader" >
<Setter Property="Foreground" Value="Blue" />
<Setter Property="ContentTemplate" >
<Setter.Value>
<DataTemplate>
<Button Content={Binding Content}" MouseDown="mouseDownEventHandler">
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.ColumnHeaderStyle>
</DataGrid>
or if you are using DataGrid.Columns to populate your columns and you need to set each of them separately, you can use this:
<DataGrid>
<DataGrid.Columns>
<DataGridTextColumn HeaderTemplate="{StaticResource MyTemplate1"/>
<DataGridHyperlinkColumn HeaderTemplate="{StaticResource MyTemplate2"/>
</DataGrid.Columns>
</DatGrid>
where MyTemplate1 and 2 should be defined previously in your control's Resources.
Edit:
The other approach according to this link is to add a PreviewMouseDown to your DataGrid and then find out if the mouse down was happend on the header or not.
This is the simple version of her event handler:
DependencyObject dep = (DependencyObject)e.OriginalSource;
while ((dep != null) && !(dep is DataGridColumnHeader))
{
dep = VisualTreeHelper.GetParent(dep);
}
if (dep == null) return;
if (dep is DataGridColumnHeader)
{
MessageBox.Show(((DataGridColumnHeader)dep).Content.ToString());
}

- 16,157
- 9
- 63
- 101
-
Any idea how I would make it highlight in blue on mouseover like the row headers do? – KrisTrip Jan 30 '12 at 18:52
-
I've googled it and found a couple of solutions for getting the click event out of the column header. one of them is using the ColumnReordering event as it's described here: http://stackoverflow.com/questions/3716819/wpf-listview-columnheader-click-event – Bizhan Jan 30 '12 at 21:27
-
I've changed my answer above. Take a look at the second part (after "Edit:") I think it will solve your problem. – Bizhan Jan 30 '12 at 21:50
You could also modify the ColumnHeaderStyle
:
In XAML:
<DataGrid>
<DataGrid.ColumnHeaderStyle>
<Style TargetType="DataGridColumnHeader">
<EventSetter Event="Click" Handler="DataGridColumnHeader_OnClick"></EventSetter>
</Style>
</DataGrid.ColumnHeaderStyle>
</DataGrid>
In the code-behind:
private void DataGridColumnHeader_OnClick(object sender, RoutedEventArgs e)
{
var columnHeader = sender as DataGridColumnHeader;
if (columnHeader != null)
{
if (!Keyboard.IsKeyDown(Key.LeftCtrl))
{
dataGrid.SelectedCells.Clear();
}
foreach (var item in dataGrid.Items)
{
dataGrid.SelectedCells.Add(new DataGridCellInfo(item, columnHeader.Column));
}
}
}

- 1,596
- 17
- 24
In WPF there is no direct support for column selection so, need to Extend existing DataGrid and add custom support for Column Selection. Below is the code that will allow used to select column on Header click. For Below code to work following setting is required.
Xaml Code:
<local:DataGridEx SelectionUnit="CellOrRowHeader" CanUserSortColumns="False"/>
C# Code:
public class DataGridEx : DataGrid
{
/// <summary>
/// Holds the column that is selected.
/// </summary>
public object SelectedColumn
{
get { return GetValue(SelectedColumnProperty); }
set { SetValue(SelectedColumnProperty, value); }
}
// Using a DependencyProperty as the backing store for SelectedColumn. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SelectedColumnProperty =
DependencyProperty.Register("SelectedColumn", typeof(object),
typeof(DataGridEx), new PropertyMetadata(null));
private T GetVisualParent<T>(DependencyObject child) where T : Visual
{
DependencyObject parent = VisualTreeHelper.GetParent(child);
if (parent == null || parent is T)
{
return parent as T;
}
else
{
return GetVisualParent<T>(parent);
}
}
protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
{
DataGridColumnHeader dataGridColumnHeader = GetVisualParent<DataGridColumnHeader>(e.OriginalSource as DependencyObject);
if (dataGridColumnHeader == null)
{
return;
}
if (SelectedCells != null && SelectedCells.Count > 0)
{
UnselectAllCells();
SelectedCells.Clear();
}
SelectedColumn = dataGridColumnHeader.Column;
foreach (var item in this.Items)
{
this.SelectedCells.Add(new DataGridCellInfo(item, dataGridColumnHeader.Column));
}
base.OnPreviewMouseDown(e);
}
}

- 21
- 3