你能在xaml的1行内使用Binding ValidationRule吗?

时间:2017-06-01 00:29:06

标签: wpf xaml

我不知道用正确的措辞来描述我在这里要做的事情......所以我只是展示它。

我知道这个xaml有效:

<TextBox>
  <TextBox.Text>
    <Binding Path="Location" UpdateSourceTrigger="PropertyChanged">
      <Binding.ValidationRules>
        <domain:NotEmptyValidationRule ValidatesOnTargetUpdated="True"/>
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
</TextBox>

但这非常冗长。我想以类似的方式做到这一点...

<TextBox Text={Binding Path=Location, UpdateSourceTrigger=PropertyChanged,
                       ValidationRules={domain:NotEmptyValidationRuleMarkup ValidateOnTargetUpdated=True}}"/>

我创建了一个名为NotEmptyValidationRuleMarkup的类,它返回NotEmptyValidationRule的实例,并且它有点可行。项目构建得很好,运行得很好,一切都按照我的预期完成。但是,我无法再在设计师中查看我的窗口。它给我一个无效的标记错误,因为The property "ValidationRules" does not have an accessible setter.。确实如此,ValidationRules没有setter。如果我尝试通过C#中的代码设置ValidationRules,我会收到编译错误。但由于某些原因,当我在XAML中分配它时,它确实构建并运行得很好。我糊涂了。有没有办法让我能够在没有抬起窗户设计视图的情况下完成这项工作?

1 个答案:

答案 0 :(得分:1)

即使xaml解释器碰巧将标记扩展转换为有效的东西,但实际上并不支持。

请参阅MSDN - Binding Markup Extension

  

以下是无法使用Binding标记扩展名/ {Binding}表达式设置的Binding属性。

     
      
  • ...

  •   
  • ValidationRules:该属性采用ValidationRule对象的通用集合。这可以表示为Binding对象元素中的属性元素,但在Binding表达式中没有现成的属性解析技术。请参阅ValidationRules的参考主题。

  •   

但是,让我建议一种不同的方法:不是在绑定中嵌套自定义标记扩展,而是将绑定嵌套在自定义标记扩展中:

[ContentProperty("Binding")]
[MarkupExtensionReturnType(typeof(object))]
public class BindingEnhancementMarkup : MarkupExtension
{
    public BindingEnhancementMarkup()
    {

    }
    public BindingEnhancementMarkup(Binding binding)
    {
        Binding = binding;
    }

    [ConstructorArgument("binding")]
    public Binding Binding { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        Binding.ValidationRules.Add(new NotEmptyValidationRule());
        return Binding.ProvideValue(serviceProvider);
    }
}

使用如下:

<TextBox Text="{local:BindingEnhancementMarkup {Binding Path=Location, UpdateSourceTrigger=PropertyChanged}}"/>

当然,对于制作而言,您可能希望在标记扩展中添加一些检查,而不是假设所有内容都已到位。