【问题标题】:Can you use a Binding ValidationRule within 1 line in xaml?您可以在 xaml 的 1 行中使用 Binding ValidationRule 吗?
【发布时间】:2019-08-19 16:47:39
【问题描述】:

我不知道正确的措辞来描述我在这里要做什么......所以我只是展示一下。

我知道这个 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 没有设置器。如果我尝试通过 C# 中的代码设置 ValidationRules,则会出现编译错误。但是由于某种原因,当我在 XAML 中分配它时,它实际上确实构建和运行得很好。我糊涂了。有没有一种方法可以在不提升窗口设计视图的情况下完成这项工作?

【问题讨论】:

  • 让我们从 为什么 它在 XAML 中工作开始...ValidationRules 是一个集合,所以它不会调用它的 setter,而是将 Add 新元素添加到收藏。我不知道将集合初始化引入标记扩展。
  • 但根据设计者的说法,它应该在 XAML 中工作,即使它正在工作。我正在尝试找到一个不会给我设计错误的解决方案,以便我仍然可以在设计模式下看到我的窗口。

标签: wpf xaml


【解决方案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}}"/>

当然,对于生产,您可能希望在标记扩展中添加更多检查,而不是仅仅假设一切就绪。

【讨论】:

  • 顺便说一句:你也可以扩展 Binding 并在其中添加验证规则而不是包装它。
猜你喜欢
  • 2011-11-29
  • 1970-01-01
  • 2018-10-22
  • 2011-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多