I'm trying to extend standard DataGrid
functionality by adding some methods and properties into a derived control:
public class ExtendedGrid : DataGrid
{
...
}
However, handling mouse events of the headers is still unclear to me. Since DataGridColumnHeader
is not a part of the visual tree (correct me if I mistake), and the only way to set an event handler to the MouseEvent
is to apply style on it ( How do I capture "Click" events on a DataGrid column headers ).
Since I'm extending the DataGrid
, I'd like to keep implementation in code, without adding any XAML, in my opiinion it's inconsistent in terms of code readability. Therefore, I wrote the following code:
private void InitializeStyles()
{
Style headerStyle = new Style(typeof(DataGridColumnHeader));
headerStyle.Setters.Add(new EventSetter(MouseDownEvent, new MouseButtonEventHandler(OnColumnHeaderMouseDown)));
foreach(var column in Columns)
{
column.HeaderStyle = headerStyle;
}
}
This code is called on AutoGeneratedColumns
and doesn't work well (eg at all). Even if it would, it would impose limitations on setting styles on headers.
Is there a way to handle DataGridColumnHeader
mouse events in my ExtendedGrid
without any XAML? Or XAML styles is anyway better than search of workarounds (and probably overcomplicationg things)?
DataGridColumnHeader
is of course part of the visual tree. It's the DataGridColumn
and its descendants that are not part of the visual tree as they serve as data objects for the actual rendered CellTemplate
or HeaderTemplate
.
Note that since DataGridColumnHeader
extends ButtonBase
, you can also execute an ICommand
that is assigned to DataGridColumnHeader.Command
.
If you want to execute the same event handler for a certain event eg, Click
for each DataGridColumnHeader
eg, in order to execute a column based sort, then you can simply register a handler for the routed event directly on the DataGrid
:
<DataGrid DataGridColumnHeader.Click="SortColumn_OnClick" />
or when using a Style
set the DataGrid.ColumnHeaderStyle
:
<DataGrid>
<DataGrid.ColumnHeaderStyle>
<Style TargetType="DataGridColumnHeader">
<EventSetter Event="Click"
Handler="SortColumn_OnClick" />
</Style>
</DataGrid.ColumnHeaderStyle>
</DataGrid>
If you are looking for a specific DataGridColumnHeader
of a column or columns, then traverse the visual tree to find them.
You can get the DataGridColumnHeader
of a certain column by handling the DataGrid.Loaded
event:
MainWindow.xaml
<DataGrid Loaded="DataGrid_OnLoaded" />
MainWindow.xaml.cs
private void DataGrid_OnLoaded(object sender, RoutedEventArgs e)
{
var dataGrid = sender as DataGrid;
foreach (DataGridColumn dataGridColumn in dataGrid.Columns)
{
if (TryFindColumnHeader(dataGrid, dataGridColumn.DisplayIndex, out DataGridColumnHeader columnHeader))
{
columnHeader.Click += (sender, args) => MessageBox.Show($"Column #{columnHeader.DisplayIndex} Header clicked");
}
}
}
public bool TryFindColumnHeader(
DependencyObject dataGrid,
int columnIndex,
out DataGridColumnHeader dataGridColumnHeader)
{
dataGridColumnHeader = null;
for (var childIndex = 0; childIndex < VisualTreeHelper.GetChildrenCount(dataGrid); childIndex++)
{
DependencyObject childElement = VisualTreeHelper.GetChild(dataGrid, childIndex);
if (childElement is DataGridColumnHeader columnHeader && columnHeader.DisplayIndex.Equals(columnIndex))
{
dataGridColumnHeader = columnHeader;
return true;
}
if (TryFindColumnHeader(childElement, columnIndex, out dataGridColumnHeader))
{
return true;
}
}
return false;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.