Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
759 views
in Technique[技术] by (71.8m points)

wpf - Can you use a Binding ValidationRule within 1 line in xaml?

I don't know the correct wording to describe what I'm trying to do here... so I'll just show it.

This xaml I know works:

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

But this is pretty verbose. I would like to do it in a way similar to this...

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

I made a class called NotEmptyValidationRuleMarkup that returns an instance of NotEmptyValidationRule, and it sort-of works. Project builds just fine, it runs just fine, everything works exactly as I expect it to. However, I can no longer view my window in the designer. It gives me an Invalid Markup error because The property "ValidationRules" does not have an accessible setter.. And it's true, ValidationRules does not have a setter. If I try to set ValidationRules through code in C# I get a compile error. But for some reason when I assign it in XAML it actually does build and run just fine. I'm confused. Is there a way I can make this work without jacking up the design view of my window?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Even though the xaml interpreter happens to turn the markup extension into something working, this is not really supported.

See MSDN - Binding Markup Extension

The following are properties of Binding that cannot be set using the Binding markup extension/{Binding} expression form.

  • ...

  • ValidationRules: the property takes a generic collection of ValidationRule objects. This could be expressed as a property element in a Binding object element, but has no readily available attribute-parsing technique for usage in a Binding expression. See reference topic for ValidationRules.

However, let me suggest a different approach: instead of nesting the custom markup extension in the binding, nest the binding in a custom markup extension:

[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);
    }
}

And use as follows:

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

Ofcourse, for production you may want to add a few more checks in the markup extension instead of just assuming everything is in place.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...