C# WPF DataGrid列标题鼠标事件
我试图通过在派生控件中添加一些方法和属性来扩展标准的C# WPF DataGrid列标题鼠标事件,c#,wpf,C#,Wpf,我试图通过在派生控件中添加一些方法和属性来扩展标准的DataGrid功能: public class ExtendedGrid : DataGrid { ... } 然而,我仍然不清楚如何处理头部的鼠标事件。由于DataGridColumnHeader不是可视化树的一部分(如果我有错误,请纠正我),为MouseeEvent设置事件处理程序的唯一方法是对其应用样式() 由于我正在扩展数据网格,我希望在代码中保留实现,而不添加任何XAML,我认为它在代码可读性方面是不一致的。因此,我编写了
DataGrid
功能:
public class ExtendedGrid : DataGrid
{
...
}
然而,我仍然不清楚如何处理头部的鼠标事件。由于DataGridColumnHeader
不是可视化树的一部分(如果我有错误,请纠正我),为MouseeEvent
设置事件处理程序的唯一方法是对其应用样式()
由于我正在扩展数据网格
,我希望在代码中保留实现,而不添加任何XAML,我认为它在代码可读性方面是不一致的。因此,我编写了以下代码:
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;
}
}
此代码在自动生成列
上被调用,无法正常工作(例如根本无法正常工作)。即使会,它也会对设置标题样式施加限制
在my
ExtendedGrid
中,有没有一种方法可以在不使用任何XAML的情况下处理DataGridColumnHeader
鼠标事件?或者XAML样式无论如何都比搜索解决方法(可能是过度复杂的事情)要好?DataGridColumnHeader
当然是可视化树的一部分。DataGridColumn
及其子体不是可视化树的一部分,因为它们用作实际渲染的cellmetplate
或HeaderTemplate
的数据对象
请注意,由于DataGridColumnHeader
扩展了ButtonBase
,因此还可以执行分配给DataGridColumnHeader.Command的ICommand
如果要为某个事件执行相同的事件处理程序,例如,为每个DataGridColumnHeader
单击,例如,为了执行基于列的排序,则可以直接在DataGrid
上注册路由事件的处理程序:
<DataGrid DataGridColumnHeader.Click="SortColumn_OnClick" />
如果要查找一列或多列的特定DataGridColumnHeader
,请遍历可视化树以找到它们。
您可以通过处理DataGrid.Loaded
事件来获取特定列的DataGridColumnHeader
:
main window.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;
}
private void DataGrid\u已加载(对象发送方,路由目标)
{
var dataGrid=发送方作为dataGrid;
foreach(dataGrid.Columns中的DataGridColumn DataGridColumn)
{
if(TryFindColumnHeader(dataGrid,dataGridColumn.DisplayIndex,out DataGridColumnHeader columnHeader))
{
columnHeader.Click+=(发送者,参数)=>MessageBox.Show($“Column#{columnHeader.DisplayIndex}标题已单击”);
}
}
}
公共布尔tryfind列标题(
DependencyObject数据网格,
int列索引,
输出DataGridColumnHeader(DataGridColumnHeader)
{
dataGridColumnHeader=null;
for(var childIndex=0;childIndex
可能您正在查找事件GridViewColumnHeader。单击
?不,我正在查找MouseDown事件,仅此而已。顺便问一下,DataGrid
是否在其代码中的某个地方以相同的方式初始化这些DataGridColumnHeader
s,因此,可以使用与您的答案类似的方法扩展此方法。DataGrid
包含一个DataGridColumnHeadersPresenter
,它生成DataGridColumnHeader
元素作为其子元素。没有可以覆盖的方法,例如,用于处理与此流程相关的事件。这是内部的。通常不需要直接访问DataGridColumnHeader
容器。若要附加命令或事件处理程序,请使用样式或事件触发器;若要自定义其外观,请使用模板。I样式或事件触发器不是选项,您必须自己挖掘DataGridColumnHeader
元素。您可以创建附加行为,并通过附加属性公开此DataGridColumnHeader
项,或扩展DataGrid
并添加相应的逻辑或创建扩展方法。这是使其可重用的唯一方法。请注意,必须加载DataGrid
,才能访问DataGridColumnHeader
项。
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;
}