如何在DataGrid列标题上捕获“Click”事件

时间:2011-05-05 09:57:31

标签: .net wpf .net-4.0

.NET 4附带的DataGrid似乎不包含列和行标题点击的事件。我想接收列标题点击的事件,因为我想提供自己的排序行为并关闭默认排序,这是因为我的视图模型是一个分页模型,一次只显示25/50/100行,默认排序当然只对当前页面进行排序。

现在我可以创建一个新的DataGridColumnHeader样式,其中包含一个可点击元素并设置ColumnHeaderStyle,虽然这看起来很痛苦,因为我很难搞清楚它是哪个列点击等等。

其他人反对这一点并解决了它?

3 个答案:

答案 0 :(得分:28)

标题只是按钮。与任何按钮一样,您可以注册Click事件来捕获这些点击。只需设置定位DataGridColumnHeader的样式并添加Click事件处理程序即可。然后在处理程序中,您可以通过sender直接访问标题。然后,您可以获得与该标题相关联的Column以及与其关联的其他信息。

<DataGrid>
    <DataGrid.Resources>
        <Style TargetType="DataGridColumnHeader">
            <EventSetter Event="Click" Handler="columnHeader_Click" />
        </Style>
    </DataGrid.Resources>
</DataGrid>

然后在代码中:

private void columnHeader_Click(object sender, RoutedEventArgs e)
{
    var columnHeader = sender as DataGridColumnHeader;
    if (columnHeader != null)
    {
        // do stuff
    }
}

进一步了解DataGrid,我注意到有一个ColumnHeaderStyle属性。我认为通过这个属性应用样式会更好。

<DataGrid>
    <DataGrid.ColumnHeaderStyle>
        <Style TargetType="DataGridColumnHeader">
            <EventSetter Event="Click" Handler="columnHeader_Click" />
        </Style>
    </DataGrid.ColumnHeaderStyle>
</DataGrid>

答案 1 :(得分:0)

也可以通过编程方式执行

using System.Windows.Controls.Primitives;

...

public TestWindow()
{
  if (TestDataGrid.ColumnHeaderStyle == null)
  {
    TestDataGrid.ColumnHeaderStyle = new Style(typeof(DataGridColumnHeader));
  }
  TestDataGrid.ColumnHeaderStyle.Setters.Add(new EventSetter(ButtonBase.ClickEvent,
       new RoutedEventHandler(TestDataGrid_HeaderRowClick)));
}


private void TestDataGrid_HeaderRowClick(object sender, RoutedEventArgs e)
{
  ...
}

当用户使用鼠标左键单击标题行时,将调用方法“ TestDataGrid_HeaderRowClick”。

答案 2 :(得分:0)

苦苦挣扎了许久,终于有了这个完整的解决方案。

在 FormMain.Designer.cs 中,添加处理程序(第二个):

    private void InitializeComponent()
    {
        ...
        this.TableOfBriefs.CellDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.TableOfBriefs_CellContentClick);
        this.TableOfBriefs.ColumnHeaderMouseClick += new DataGridViewCellMouseEventHandler(this.TableOfBriefs_HeaderClick);

在 Forman.cs 中,添加方法:

    private readonly Dictionary<string, bool> _columnName2Orders = new Dictionary<string, bool>();
    private const bool IsAscendingWhenFirstClicked = false;
    private void TableOfBriefs_HeaderClick(object sender, DataGridViewCellMouseEventArgs e)
    {
        if (!(sender is DataGridView dataGrid))
            throw new ArgumentException(@$"{sender} is not a {typeof(DataGridView)}.");

        var column = dataGrid.Columns[e.ColumnIndex];
        var propertyInfo = typeof(CciSingleFileResultBrief).GetProperty(column.Name);
        if (propertyInfo == null)
            throw new ArgumentException($@"There is no property named {column.Name} found in class {typeof(CciSingleFileResultBrief)}.");

        if (!_columnName2Orders.ContainsKey(propertyInfo.Name))
            _columnName2Orders.Add(propertyInfo.Name, IsAscendingWhenFirstClicked);
        _columnName2Orders[propertyInfo.Name] = !_columnName2Orders[propertyInfo.Name];

        var isAscending = _columnName2Orders[propertyInfo.Name];
        var briefs = isAscending ? _briefs.OrderByDescending(i => propertyInfo.GetValue(i)).ToList()
                : _briefs.OrderBy(i => propertyInfo.GetValue(i)).ToList();
        TableOfBriefs.DataSource = briefs;
    }