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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 13:45:32