如何将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
相关产品推荐
相关产品推荐

