WPF的DataGridTextColumn能否复用实体类的MaxLength特性?
让WPF DataGridTextColumn复用实体类的MaxLength特性
完全不需要分别在EF和WPF里重复设置长度限制,通过以下两种方式可以直接复用实体类上的MaxLengthAttribute:
方法一:使用附加属性自动读取特性
创建一个附加属性,在TextBox加载时自动解析绑定属性对应的实体类特性,设置MaxLength:
C# 附加属性实现
using System.ComponentModel.DataAnnotations; using System.Reflection; using System.Windows; using System.Windows.Controls; public static class TextBoxMaxLengthHelper { public static readonly DependencyProperty BindMaxLengthFromPropertyAttributeProperty = DependencyProperty.RegisterAttached( "BindMaxLengthFromPropertyAttribute", typeof(bool), typeof(TextBoxMaxLengthHelper), new PropertyMetadata(false, OnBindMaxLengthFromPropertyAttributeChanged)); public static bool GetBindMaxLengthFromPropertyAttribute(DependencyObject obj) { return (bool)obj.GetValue(BindMaxLengthFromPropertyAttributeProperty); } public static void SetBindMaxLengthFromPropertyAttribute(DependencyObject obj, bool value) { obj.SetValue(BindMaxLengthFromPropertyAttributeProperty, value); } private static void OnBindMaxLengthFromPropertyAttributeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is TextBox textBox && (bool)e.NewValue) { textBox.Loaded += TextBox_Loaded; } } private static void TextBox_Loaded(object sender, RoutedEventArgs e) { if (sender is TextBox textBox && textBox.GetBindingExpression(TextBox.TextProperty) is { } bindingExpr) { var propertyPath = bindingExpr.ParentBinding.Path.Path; var dataItemType = textBox.DataContext.GetType(); var propertyInfo = dataItemType.GetProperty(propertyPath); if (propertyInfo != null) { var maxLengthAttr = propertyInfo.GetCustomAttribute<MaxLengthAttribute>(); if (maxLengthAttr != null) { textBox.MaxLength = maxLengthAttr.Length; } } } } }
XAML 使用方式
修改你的DataGridTextColumn样式,添加附加属性即可:
<DataGridTextColumn Header="Xyz" Width="*" Binding="{Binding Xyz}"> <DataGridTextColumn.EditingElementStyle> <Style TargetType="{x:Type TextBox}"> <Setter Property="local:TextBoxMaxLengthHelper.BindMaxLengthFromPropertyAttribute" Value="True"/> </Style> </DataGridTextColumn.EditingElementStyle> </DataGridTextColumn>
方法二:使用自定义MarkupExtension直接获取特性值
创建一个MarkupExtension,直接在XAML中指定实体类和属性名,读取对应的MaxLength值:
C# MarkupExtension实现
using System.ComponentModel.DataAnnotations; using System.Reflection; using System.Windows.Markup; public class MaxLengthExtension : MarkupExtension { public string PropertyName { get; set; } public Type DataType { get; set; } public override object ProvideValue(IServiceProvider serviceProvider) { if (string.IsNullOrEmpty(PropertyName) || DataType == null) return int.MaxValue; var propertyInfo = DataType.GetProperty(PropertyName); if (propertyInfo == null) return int.MaxValue; var maxLengthAttr = propertyInfo.GetCustomAttribute<MaxLengthAttribute>(); return maxLengthAttr?.Length ?? int.MaxValue; } }
XAML 使用方式
直接在Setter的Value中调用该扩展,指定实体类型和属性名:
<DataGridTextColumn Header="Xyz" Width="*" Binding="{Binding Xyz}"> <DataGridTextColumn.EditingElementStyle> <Style TargetType="{x:Type TextBox}"> <Setter Property="MaxLength" Value="{local:MaxLength PropertyName=Xyz, DataType={x:Type local:YourEntityClass}}"/> </Style> </DataGridTextColumn.EditingElementStyle> </DataGridTextColumn>
说明
- 方法一无需手动指定实体类和属性名,自动关联绑定的属性,适合批量使用;
- 方法二需要明确指定实体类型和属性名,适合需要精准控制的场景;
- 两种方式都能避免硬编码长度值,实现EF和WPF的配置统一。
内容的提问来源于stack exchange,提问作者hardfork
相关产品推荐
相关产品推荐

