将DataContext绑定到ValidationRule

Mar*_*ins 10 .net wpf binding

我有一个自定义ValidationRule,需要访问ViewModel,以便与ViewModel的其他属性一起验证提供的值.我以前试图通过使用ValidationGroup来实现这一点,但放弃了这个想法,因为我修改的代码需要大量重构才能启用此路由.

在新闻组中发现了一个线程,它显示了一种绑定控件的DataContext的方法,其中ValidationRule通过继承自DependencyObject的中间类运行到ValidationRule,但是我无法让它绑定.

有人可以帮忙吗?

我的ValidationRule如下......

class TotalQuantityValidator : CustomValidationRule {

    public TotalQuantityValidator()
        : base(@"The total number must be between 1 and 255.") {
    }

    public TotalQuantityValidatorContext Context { get; set; }

    public override ValidationResult Validate(object value, CultureInfo cultureInfo) {

        ValidationResult validationResult = ValidationResult.ValidResult;

        if (this.Context != null && this.Context.ViewModel != null) {

            int total = ...
            if (total <= 0 || total > 255) {
                validationResult = new ValidationResult(false, this.ErrorMessage);
            }

        }

        return validationResult;

    }

}
Run Code Online (Sandbox Code Playgroud)

CustomValidationRule定义如下......

public abstract class CustomValidationRule : ValidationRule {

    protected CustomValidationRule(string defaultErrorMessage) {
        this.ErrorMessage = defaultErrorMessage;
    }

    public string ErrorMessage { get; set; }

}
Run Code Online (Sandbox Code Playgroud)

TotalQuantityValidatorContext定义如下......

public class TotalQuantityValidatorContext : DependencyObject {

    public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(@"ViewModel",
        typeof(MyViewModel), typeof(TotalQuantityValidatorContext),
        new PropertyMetadata {
            DefaultValue = null,
            PropertyChangedCallback = new PropertyChangedCallback(TotalQuantityValidatorContext.ViewModelPropertyChanged)
        });

    public MyViewModel ViewModel {
        get { return (MyViewModel)this.GetValue(TotalQuantityValidatorContext.ViewModelProperty); }
        set { this.SetValue(TotalQuantityValidatorContext.ViewModelProperty, value); }
    }

    private static void ViewModelPropertyChanged(DependencyObject element, DependencyPropertyChangedEventArgs args) {
    }

}
Run Code Online (Sandbox Code Playgroud)

因此整个事情都被使用了......

<UserControl x:Class="..."
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:val="clr-namespace:Validators" x:Name="myUserControl">

    <TextBox Name="myTextBox">
        <TextBox.Text>
            <Binding NotifyOnValidationError="True" Path="myViewModelProperty" UpdateSourceTrigger="PropertyChanged">
                <Binding.ValidationRules>
                    <val:TotalQuantityValidator>
                        <val:TotalQuantityValidator.Context>
                            <val:TotalQuantityValidatorContext ViewModel="{Binding ElementName=myUserControl, Path=DataContext}" />
                        </val:TotalQuantityValidator.Context>
                    </val:TotalQuantityValidator>
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>

</UserControl>
Run Code Online (Sandbox Code Playgroud)

UserControl的DataContext被设置为代码隐藏中的MyViewModel实例.我知道这个绑定有效,因为标准控件绑定按预期运行.

TotalQuantityValidator.Validate正确调用该方法,但每当我查看其ViewModel属性时Context,它始终为null(正在设置为正确实例的Context属性).我可以从调试器中看到,从不调用属性的setter .TotalQuantityValidatorTotalQuantityValidatorContextViewModelTotalQuantityValidatorContext

任何人都可以建议我如何使这个绑定工作?

提前致谢.

Ian*_*ths 6

我会避免使用验证规则.如果您需要访问viewmodel中的信息来执行验证,那么最好将验证逻辑放在viewmodel本身中.

您可以使您的viewmodel实现IDataErrorInfo,并简单地打开绑定上基于数据错误信息的验证.

即使您没有遇到需要上下文信息的这个(非常常见的)问题,验证规则也不是表达验证的好方法:验证规则通常与业务逻辑相关,或者至少与信息的语义方面相关.Xaml似乎是放置这些东西的错误位置 - 为什么我会在源文件中放置业务规则,其主要工作是确定应用程序的布局和可视化设计?

验证逻辑属于您的应用程序.即使是viewmodel也可能是错误的层,但在这种情况下,您可以简单地让viewmodel负责找出验证逻辑的位置.


Mar*_*ins 5

我刚刚找到了一个完美的答案!

如果将ValidationRule的ValidationStep属性设置为ValidationStep.UpdatedValue,则传递给Validate方法的值实际上是BindingExpression.然后,您可以询问BindingExpression对象的DataItem属性,以获取绑定绑定的模型.

这意味着我现在可以根据需要验证已分配的值以及其他属性的现有值.