【问题标题】:How do I capture "Click" events on a DataGrid column headers如何捕获 DataGrid 列标题上的“单击”事件
【发布时间】:2011-08-19 05:50:03
【问题描述】:

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

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

还有其他人反对并解决了吗?

【问题讨论】:

    标签: .net wpf .net-4.0


    【解决方案1】:

    标题只是按钮。像任何按钮一样,您可以注册到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>
    

    【讨论】:

    • 非常感谢Jeff,我以前从未使用过EventSetter,非常方便。我有一个后续问题,你知道是否有可能在CanUserSortColumns="False" 时获得样式行为,以便标题响应鼠标悬停并显示排序方向,还是我需要自己重新设置这些样式?
    • @Brett:对不起,你能改一下吗?我不确定我明白你在问什么。在我看来,您想在禁用排序时获取与这些标题关联的模板?
    • 谢谢杰夫,很抱歉有歧义。我想要做的是提供我自己的排序逻辑,在你的帮助下我现在已经实现了这一点,但是我当然必须将CanUserSortColumns 设置为False 否则控件将尝试执行排序错误,但是我希望在将光标移动到列标题上时产生良好的“悬停”效果,并且希望“向上/向下”箭头指示排序方向(尽管后者不太重要)。非常感谢您的帮助。
    • @Brett:我很确定你可以,我只是不记得如何诚实。虽然我会调查。您可能想将其作为另一个问题发布。
    • @Brett:查看我的更新。以防万一您还没有注意到这一点。
    【解决方案2】:

    也可以以编程方式

    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”方法,当用户用鼠标左键点击标题行时。

    【讨论】:

      【解决方案3】:

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

      在FormMain.Designer.cs中,添加handler(第二个):

          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;
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-01-11
        • 1970-01-01
        • 1970-01-01
        • 2012-11-16
        • 2023-03-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多