【问题标题】:How does the IDataErrorInfo interface work?IDataErrorInfo 接口如何工作?
【发布时间】:2010-06-24 10:48:05
【问题描述】:

我目前正在研究我的 WPF 应用程序的验证,并看到提到了 IDataErrorInfo。然而,关于如何使用它的指南很少,更糟糕的是,没有人解释它是如何工作的。

在 MSND.com 网站上给出: MSDN

public class Person : IDataErrorInfo
{
    private int age;
    public int Age
    {
        get { return age; }
        set { age = value; }
    }

    public string Error
    {
        get
        {
            return null;
        }
    }

    public string this[string name]
    {
        get
        {
            string result = null;
            if (name == "Age")
            {
                if (this.age < 0 || this.age > 150)
                {
                    result = "Age must not be less than 0 or greater than 150.";
                }
            }
            return result;
        }
    }
}

我知道这里发生了什么,但我不知道它对我的数据的真正作用。

这两个属性什么时候使用?假设有人将Age 设置为 400:调用了属性上的设置器。错误会阻止它被设置吗?如果不是,它只是警告数字不正确,有什么办法阻止某人按原样保存信息?没有IsValid() 方法可以检查,是吗?

很想知道窗帘后面发生了什么。

【问题讨论】:

    标签: wpf idataerrorinfo


    【解决方案1】:

    Error 属性通常不使用,但您必须定义它才能实现接口。 正如 decyclone 所说,验证不会阻止属性被设置为错误的值,但您可以将属性设置为默认值。 让我告诉你我是如何使用它的。我有几个TextBoxes,我必须验证它们的值。我不想在调用集合时显示带有错误的 MessageBox,而是采用“webly”方法:我希望 TextBox 的边框和背景在设置无效值时为红色,并且工具提示TextBox 显示它得到的错误。

    这是我的 TextBox 的 xaml:

    <converters:ValidationConverter x:Key="validationConverter"/>
    <Style x:Key="TestStepTextBox" TargetType="{x:Type TextBox}">
        <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBox}">
                    <Border x:Name="Bd" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                        <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="Validation.HasError" Value="true">
                            <Setter Property="ToolTip"
                                    Value="{Binding RelativeSource={RelativeSource Self}, 
                                    Converter={StaticResource validationConverter}, Path=(Validation.Errors)}"/>
                            <Setter Property="Background" Value="#33FF342D"/>
                            <Setter Property="BorderBrush" Value="#AAFF342D"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    
    <TextBox Name="txtRunAfter" Text="{Binding RunAfter, ValidatesOnDataErrors=True, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged}" Style="{DynamicResource TestStepTextBox}"/>
    <TextBox Name="txtStopAfter" Text="{Binding StopAfter, ValidatesOnDataErrors=True, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged}" Style="{DynamicResource TestStepTextBox}"/>
    

    关于转换器的非常重要的说明。当我输入一个无效的值然后我设置了一个好的值时,我遇到了一个异常。不知何故,可能与拥有UpdateSourceTrigger=PropertyChanged 有关,有一段时间 HasError 属性为真但没有设置错误(请参阅link)。所以这里是转换器的代码:

    public class ValidationConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            ReadOnlyObservableCollection<ValidationError> errors = value as ReadOnlyObservableCollection<ValidationError>;
            if (errors == null) return value;
            if (errors.Count > 0)
            {
                return errors[0].ErrorContent;
            }
            return "";
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException("This method should never be called");
        }
    }
    

    为了防止无效值被保存到我的模型层,我使用相同的方法来检查我是否应该将数据提交到模型。如果该值无效,我只设置属性并且不调用模型中的一组属性。检查代码:

    private int _runAfter = 0;
    public int RunAfter
    {
        get
        {
            return _runAfter;
        }
    
        set
        {
            if (_runAfter != value)
            {
                _runAfter = value;
                OnPropertyChanged("RunAfter");
    
                if (validateRunAfter() == null)
                    setRunAfter(); //sets the property value to the model layer
            }
        }
    }
    
    string IDataErrorInfo.this[string columnName]
    {
        get
        {
            string message = null;
            if (columnName == "RunAfter")
                message = validateRunAfter();
            //...
            return message;
        }
    }
    
    private string validateRunAfter()
    {
        if (value >= _order)
            return "Run After value must be less than its Step Order (#) value.";
    
        return null;
    }
    

    【讨论】:

    • 谢谢您,我没有时间正确检查此问题,但如果一切顺利,将给您正确答案;)
    【解决方案2】:

    我所知道的IDataErrorInfo 仅用于UI 目的。它的作用是提供一种将错误消息绑定到WPF UI 的简单方法。由于WPF UIINotifyPropertyChanged 一样“识别”了实现IDataErrorInfo 的对象,因此您不必编写额外的代码来显示UI 中的错误消息。

    还有一件事,它不会停止设置错误的值。它只会告诉WPF UI(当WPF UI 调用提供属性名称的索引器时)特定属性中的值无效。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-03
    • 1970-01-01
    • 1970-01-01
    • 2011-05-29
    • 1970-01-01
    • 2015-11-20
    • 2012-11-09
    相关资源
    最近更新 更多