如何使用IDataErrorInfo验证父类中的子对象?

时间:2017-08-14 15:05:30

标签: c# wpf validation

我有一个类DataModel,它有一堆对象,它们都是同一个类InputItemInputItem类有一个可为空的十进制属性Value,我要在DataModel类中验证({{>} 在InputItem类中) 。这是因为一个InputItem对象的验证取决于另一个 InputItem对象中的值。我希望IDataErrorInfo用于此目的,但尚未能使其正常工作(此代码允许我绑定InputItem中的值,但不会# 39;执行任何验证。

我的DataModel类:

using System.ComponentModel;

public class DataModel : IDataErrorInfo
{
    public InputItem Item1 {get; set;}
    public InputItem Item2 {get; set;}
    public InputItem Item3 {get; set;}
    //... more InputItem objects

    public string Error { get { return string.Empty;} }

    public string this[string propertyName]
    {
        get
        {
            string result = string.Empty;
            switch (propertyName)
            {
                case "Item1":
                case "Item1.Value":
                    if (Item1.Value == null)
                        result = "Item 1 is required.";
                    else if (Item1.Value < 0)
                        result = "Item 1 must be greater than 0.";
                    break;
                case "Item2":
                case "Item2.Value":
                    if (Item2.Value == null)
                        result = "Item 2 is required.";
                    else if (Item2.Value < Item1.Value)
                        result = "Item 2 must be greater than item 1";
                    break;
                case "Item3":
                case "Item3.Value":
                    if (Item3.Value == null)
                        result = empty.String;
                    else if (Item3.Value < Item1.Value)
                        result = "Item 3 must be greater than Item 1."
                    else if (Item3.Value > Item2.Value)
                        result = "Item 3 must be less than Item 2."
            }
            return result;
        }
    }
}

public class InputItem : INotifyPropertyChanged
{
    //Implements INotifyPropertyChanged, but I'm leaving it out to shorten the code

    public string Name {get; set;}

    public decimal? Value {get; set;}

    public string Unit {get; set;}

    public string Tip { get; set; }

    //... more properties

    // ... Standard constructors
}

最终,我想将XAML视图中某些TextBox个对象的某些属性绑定到不同InputItem个对象中的属性,就像这样(使用视图&#39; s {{ 1}}设置为DataContext对象):

DataModel

以前,我尝试为每个具有最小和最大允许值的InputItem对象设置验证规则,然后将验证规则中的最小值和最大值绑定到其他InputItem对象中的值,但是您可以从我的描述,这变得复杂和快速纠结。 以下是我用于<TextBox Text="{Binding Path=Item1.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"/> 和绑定策略的代码,以防您感兴趣:

ValidationRule

我已经查看了How to validate child objects by implementing IDataErrorInfo on parent class,但它并不适用于这种情况(该人真的想要自己验证各个子对象,而不是通过父对象)。 / p>

我还查看了this post by Brian Lagunas,但它也不适用,因为每个using System.Globalization; using System.Windows; using System.Windows.Controls; public class NumberValidationRuleWithWrapper : ValidationRule { public override ValidationResult Validate(object value, CultureInfo cultureInfo) { decimal result = 0; bool canConvert = decimal.TryParse(value as string, out result); if (!canConvert) return new ValidationResult(false, "Must be a valid number"); decimal? maxval = this.Wrapper.MaxValue; if (maxval != null && !double.IsNaN((double)maxval)) { if (result >= maxval) return new ValidationResult(false, "Must be less than " + ((decimal)maxval).ToString()); } decimal? minVal = this.Wrapper.MinValue; if (minVal != null && !double.IsNaN((double)minVal)) { if (result <= minVal) return new ValidationResult(false, "Must be greater than " + ((decimal)minVal).ToString()); } return ValidationResult.ValidResult; } public DecimalWrapper Wrapper { get; set; } } public class DecimalWrapper : DependencyObject { public static readonly DependencyProperty MaxValueProperty = DependencyProperty.Register("MaxValue", typeof(double?), typeof(DecimalWrapper), new FrameworkPropertyMetadata(double.MaxValue)); public static readonly DependencyProperty MinValueProperty = DependencyProperty.Register("MinValue", typeof(double?), typeof(DecimalWrapper), new FrameworkPropertyMetadata(double.MinValue)); public decimal? MaxValue { get { return (decimal?)GetValue(MaxValueProperty); } set { SetValue(MaxValueProperty, value); } } public decimal? MinValue { get { return (decimal?)GetValue(MinValueProperty); } set { SetValue(MinValueProperty, value); } } } 对象都有与其他InputItem对象相关的不同规则(例如Item1 can是任何数字,Item2必须小于Item1,Item3必须在Item1和Item2之间,Item4必须大于Item3,等等。

1 个答案:

答案 0 :(得分:1)

绑定到Item1.Value时,只有IDataErrorInfo属性所属类型的Value实现,即InputItem才重要。 DataModel是否实现IDataErrorInfo无关紧要。

.NET Framework 4.5中嵌入的INotifyDataErrorInfo接口使WPF数据验证更加灵活。

如果要在DataModel类中执行验证,可以在InputItem类中实现此接口,并设置从GetErrors方法返回的实际错误并引发{来自ErrorsChanged类的{1}}事件。有一个如何实现此处可用界面的示例:https://social.technet.microsoft.com/wiki/contents/articles/19490.wpf-4-5-validating-data-in-using-the-inotifydataerrorinfo-interface.aspx