WPF TextBox MaxLength – 有没有办法将它绑定到绑定字段上的数据validation最大长度?

视图模型:

public class MyViewModel { [Required, StringLength(50)] public String SomeProperty { ... } } 

XAML:

  

有没有办法避免设置TextBox的MaxLength以匹配我的ViewModel(由于它在不同的程序集中可能会改变)并让它根据StringLength要求自动设置最大长度?

我使用Behavior将TextBox连接到其绑定属性的validation属性(如果有)。 行为如下所示:

 ///  /// Set the maximum length of a TextBox based on any StringLength attribute of the bound property ///  public class RestrictStringInputBehavior : Behavior { protected override void OnAttached() { AssociatedObject.Loaded += (sender, args) => setMaxLength(); base.OnAttached(); } private void setMaxLength() { object context = AssociatedObject.DataContext; BindingExpression binding = AssociatedObject.GetBindingExpression(TextBox.TextProperty); if (context != null && binding != null) { PropertyInfo prop = context.GetType().GetProperty(binding.ParentBinding.Path.Path); if (prop != null) { var att = prop.GetCustomAttributes(typeof(StringLengthAttribute), true).FirstOrDefault() as StringLengthAttribute; if (att != null) { AssociatedObject.MaxLength = att.MaximumLength; } } } } } 

您可以看到,该行为只是检索文本框的数据上下文及其“Text”的绑定表达式。 然后它使用reflection来获取“StringLength”属性。 用法是这样的:

       

您也可以通过扩展TextBox添加此function,但我喜欢使用行为,因为它们是模块化的。

虽然我不打算完全自己编写代码,但有一个想法是创建自己的MarkupExtension ,它将获取属性名称并反映查找StringLengthAttribute

如果该属性存在,请尝试将目标绑定到该值(使用reflection)。 如果不是,则将0绑定到目标值(默认值为0,即无最大值)。

一种方法是在同一个名为SomePropertyMaxLength的视图模型中创建一个属性,然后将MaxLength属性绑定到该属性。

  

Markup扩展肯定是要走的路。 我正在创建一个名为Binding的BindingDecoratorBase的子类,它具有模型DataType依赖项属性。 由于MarkupExtensions是在InitializeComponent()期间创建的,因此无法确定DataContext,因为它尚未设置。

提供模型类型允许对模型上定义的属性进行reflection访问。 这允许:

  • 为TextBoxes设置MaxLength。
  • 为TextBlocks设置StringFormat。
  • 根据成员数据类型设置默认转换器。
  • 添加所需的validation。 使用绑定的ValidationRules或设置ValidatesOnDataErrors。

标记看起来像:Text =“{PO:Binding DataType = model:modAccount,Path = SubAccount}”

格式化,MaxLength和转换集合在一个包中,无需在模型类更改时更改任何内容。