简体   繁体   English

WPF DataGrid 列 header 鼠标事件

[英]WPF DataGrid column header mouse events

I'm trying to extend standard DataGrid functionality by adding some methods and properties into a derived control:我正在尝试通过将一些方法和属性添加到派生控件中来扩展标准DataGrid功能:

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 ).由于DataGridColumnHeader不是可视树的一部分(如果我错了,请纠正我),并且将事件处理程序设置为MouseEvent的唯一方法是在其上应用样式( 如何在 DataGrid 列标题上捕获“单击”事件)。

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.由于我正在扩展DataGrid ,我想在代码中保留实现,而不添加任何 XAML,在我看来,它在代码可读性方面是不一致的。 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).此代码在AutoGeneratedColumns上调用,但效果不佳(例如,根本没有)。 Even if it would, it would impose limitations on setting styles on headers.即使这样,它也会对在标头上设置 styles 施加限制。

Is there a way to handle DataGridColumnHeader mouse events in my ExtendedGrid without any XAML?有没有办法在没有任何 XAML 的情况下处理我的ExtendedGrid中的DataGridColumnHeader鼠标事件? Or XAML styles is anyway better than search of workarounds (and probably overcomplicationg things)?或者 XAML styles 无论如何都比寻找解决方法(并且可能过于复杂的事情)更好?

DataGridColumnHeader is of course part of the visual tree. DataGridColumnHeader当然是可视化树的一部分。 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 . DataGridColumn及其后代不属于可视化树,因为它们充当实际呈现的CellTemplateHeaderTemplate的数据对象。

Note that since DataGridColumnHeader extends ButtonBase , you can also execute an ICommand that is assigned to DataGridColumnHeader.Command .请注意,由于DataGridColumnHeader扩展了ButtonBase ,您还可以执行分配给DataGridColumnHeader.CommandICommand

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 :如果您想为某个事件执行相同的事件处理程序,例如, Click每个DataGridColumnHeader ,例如,为了执行基于列的排序,那么您可以直接在DataGrid上为路由事件注册一个处理程序:

<DataGrid DataGridColumnHeader.Click="SortColumn_OnClick" />

or when using a Style set the DataGrid.ColumnHeaderStyle :或者当使用Style设置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.如果您正在寻找一列或多列的特定DataGridColumnHeader ,则遍历可视化树以查找它们。
You can get the DataGridColumnHeader of a certain column by handling the DataGrid.Loaded event:您可以通过处理DataGrid.Loaded事件来获取某一列的DataGridColumnHeader

MainWindow.xaml主窗口.xaml

<DataGrid Loaded="DataGrid_OnLoaded" />

MainWindow.xaml.cs主窗口.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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM