You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将WPF DataGrid行头点击的EventSetter处理代码移出代码后置文件

解决方案:通过附加属性实现DataGrid行头点击添加新行

最适配你需求的方案是附加属性,它能把行头点击添加行的逻辑封装成可复用的独立行为,完全脱离代码后置文件,同时直接与DataGrid控件交互。

1. 实现附加属性类

创建一个静态类,定义控制行为的附加属性,并将原点击逻辑封装进去:

using System;
using System.Collections;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

public static class DataGridRowHeaderBehavior
{
    public static readonly DependencyProperty EnableAddRowOnClickProperty =
        DependencyProperty.RegisterAttached(
            "EnableAddRowOnClick",
            typeof(bool),
            typeof(DataGridRowHeaderBehavior),
            new PropertyMetadata(false, OnEnableAddRowOnClickChanged));

    public static bool GetEnableAddRowOnClick(DependencyObject obj)
    {
        return (bool)obj.GetValue(EnableAddRowOnClickProperty);
    }

    public static void SetEnableAddRowOnClick(DependencyObject obj, bool value)
    {
        obj.SetValue(EnableAddRowOnClickProperty, value);
    }

    private static void OnEnableAddRowOnClickChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is DataGridRowHeader rowHeader)
        {
            if ((bool)e.NewValue)
            {
                rowHeader.Click += RowHeader_Click;
            }
            else
            {
                rowHeader.Click -= RowHeader_Click;
            }
        }
    }

    private static void RowHeader_Click(object sender, RoutedEventArgs e)
    {
        if (sender is DependencyObject rowHeader)
        {
            var dataGrid = FindVisualParent<DataGrid>(rowHeader);
            if (dataGrid?.ItemsSource is IList list)
            {
                var itemType = list.GetType().GetGenericArguments()[0];
                var newItem = Activator.CreateInstance(itemType);
                var newItemIndex = list.Add(newItem);

                // 等待布局更新后选中新行
                EventHandler layoutUpdatedHandler = null;
                layoutUpdatedHandler = (s, ea) =>
                {
                    if (dataGrid.SelectedIndex != newItemIndex)
                    {
                        dataGrid.SelectedIndex = newItemIndex;
                        dataGrid.LayoutUpdated -= layoutUpdatedHandler;
                    }
                };
                dataGrid.LayoutUpdated += layoutUpdatedHandler;
            }
        }
    }

    // 视觉树父元素查找方法
    private static T FindVisualParent<T>(DependencyObject child) where T : DependencyObject
    {
        var parent = VisualTreeHelper.GetParent(child);
        if (parent == null) return null;

        if (parent is T parentT)
        {
            return parentT;
        }
        return FindVisualParent<T>(parent);
    }
}

2. 在XAML中应用附加属性

替换原EventSetter,直接在DataGridRowHeader的Style中设置附加属性即可:

<DataGrid.RowHeaderStyle>
    <Style TargetType="{x:Type DataGridRowHeader}" BasedOn="{StaticResource MahApps.Styles.DataGridRowHeader}">
        <Setter Property="Content" Value="{Binding Path=Id, Mode=OneWay, FallbackValue=*}" />
        <!-- 启用行头点击添加新行的行为 -->
        <Setter Property="local:DataGridRowHeaderBehavior.EnableAddRowOnClick" Value="True" />
    </Style>
</DataGrid.RowHeaderStyle>

方案说明

  • 附加属性完全封装了行为逻辑,可在任意DataGrid的行头样式中复用,无需重复编写代码后置逻辑。
  • 逻辑直接操作DataGrid控件,符合你不放入ViewModel的要求。
  • 内置了视觉树父元素查找方法,无需依赖外部Helper类(若你的项目已有DependencyObjectHelpers,可直接替换为自身实现)。

内容的提问来源于stack exchange,提问作者Marcus Runge

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 13:07:44