Wpf IDataErrorInfo-首次加载视图时,最初忽略错误

Wpf IDataErrorInfo-首次加载视图时,最初忽略错误,wpf,validation,idataerrorinfo,wpf-4.0,Wpf,Validation,Idataerrorinfo,Wpf 4.0,我试图使用IDataErrorInfo验证我的模型类,如下所示 //Validators public string this[string propertyName] { get { string error = null; if (propertyName == "Name") { error = ValidateName(); } return error; } } 这可以正常工作

我试图使用IDataErrorInfo验证我的模型类,如下所示

//Validators
public string this[string propertyName] {
    get {
        string error = null;

        if (propertyName == "Name") {
            error = ValidateName(); 
        }
        return error;
    }
}
这可以正常工作,只是当视图首次加载时,它已经包含验证错误。首次加载视图时是否可以忽略/抑制验证错误。此外,在加载视图时以及用户开始输入模型属性的数据之前显示错误也是一种常见做法

问候,, 尼尔万

编辑: 这就是我设置IDataErrorInfo的方式

<TextBox Text="{Binding Name, ValidatesOnDataErrors=True}" Grid.Row="1" Grid.Column="1" />

是否在get中抛出异常

public string Name
{
    get { return _name; }
    set
    {
        _name = value;
        if (String.IsNullOrEmpty(value))
        {
            throw new ApplicationException("Customer name is mandatory.");
        }
    }
}

在ValidateName()方法中设置规则。您的视图只显示了错误:)我建议名称是必填字段,应该由用户填写,但您不喜欢第一次加载视图时的红色边框

我使用两种不同的控件模板进行验证。errortemplate普通模板和一种用于必填字段(红色*)


我上次做的方式。

我采用了以下方法,效果很好。基本上,模型应该正确地记录错误并将它们列在字典中,即使对象刚刚实例化,用户还没有输入任何文本。所以我没有更改我的模型代码或IDataErrorInfo验证代码。相反,我只是最初将Validation.Error模板属性设置为{x:Null}。然后是连接文本框的LostFocus事件的代码,该事件将Validation.Error模板更改回我正在使用的模板。为了实现模板交换和将LostFocus事件处理程序附加到我的应用程序中的所有TextBox,我使用了几个依赖属性。这是我使用的代码

依赖项属性和LostFocus代码:

    public static DependencyProperty IsDirtyEnabledProperty = DependencyProperty.RegisterAttached("IsDirtyEnabled",
             typeof(bool), typeof(TextBoxExtensions), new PropertyMetadata(false, OnIsDirtyEnabledChanged));
    public static bool GetIsDirtyEnabled(TextBox target) {return (bool)target.GetValue(IsDirtyEnabledProperty);}
    public static void SetIsDirtyEnabled(TextBox target, bool value) {target.SetValue(IsDirtyEnabledProperty, value);}

    public static DependencyProperty ShowErrorTemplateProperty = DependencyProperty.RegisterAttached("ShowErrorTemplate",
             typeof(bool), typeof(TextBoxExtensions), new PropertyMetadata(false));
    public static bool GetShowErrorTemplate(TextBox target) { return (bool)target.GetValue(ShowErrorTemplateProperty); }
    public static void SetShowErrorTemplate(TextBox target, bool value) { target.SetValue(ShowErrorTemplateProperty, value); }

    private static void OnIsDirtyEnabledChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) {
        TextBox textBox = (TextBox)dependencyObject;
        if (textBox != null) {
            textBox.LostFocus += (s, e) => {
                if ((bool) textBox.GetValue(ShowErrorTemplateProperty) == false) {
                    textBox.SetValue(ShowErrorTemplateProperty, true);
                }
            };
        }
    }
<Style TargetType="{x:Type TextBox}">
    <Setter Property="Validation.ErrorTemplate" Value="{StaticResource ValidationErrorTemplate}"/>
    <Setter Property="gs:TextBoxExtensions.IsDirtyEnabled" Value="True" />
    <Style.Triggers>
        <Trigger Property="gs:TextBoxExtensions.ShowErrorTemplate" Value="false">
            <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
        </Trigger>
    </Style.Triggers>
</Style>
如果IsDirtyEnabled dependency属性设置为true,它将使用回调将TextBox的LostFocus事件附加到处理程序。该处理程序只需将ShowErrorTemplate attached属性更改为true,当textbox失去焦点时,该属性会在textbox的样式触发器中触发以显示Validation.Error模板

文本框样式:

    public static DependencyProperty IsDirtyEnabledProperty = DependencyProperty.RegisterAttached("IsDirtyEnabled",
             typeof(bool), typeof(TextBoxExtensions), new PropertyMetadata(false, OnIsDirtyEnabledChanged));
    public static bool GetIsDirtyEnabled(TextBox target) {return (bool)target.GetValue(IsDirtyEnabledProperty);}
    public static void SetIsDirtyEnabled(TextBox target, bool value) {target.SetValue(IsDirtyEnabledProperty, value);}

    public static DependencyProperty ShowErrorTemplateProperty = DependencyProperty.RegisterAttached("ShowErrorTemplate",
             typeof(bool), typeof(TextBoxExtensions), new PropertyMetadata(false));
    public static bool GetShowErrorTemplate(TextBox target) { return (bool)target.GetValue(ShowErrorTemplateProperty); }
    public static void SetShowErrorTemplate(TextBox target, bool value) { target.SetValue(ShowErrorTemplateProperty, value); }

    private static void OnIsDirtyEnabledChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) {
        TextBox textBox = (TextBox)dependencyObject;
        if (textBox != null) {
            textBox.LostFocus += (s, e) => {
                if ((bool) textBox.GetValue(ShowErrorTemplateProperty) == false) {
                    textBox.SetValue(ShowErrorTemplateProperty, true);
                }
            };
        }
    }
<Style TargetType="{x:Type TextBox}">
    <Setter Property="Validation.ErrorTemplate" Value="{StaticResource ValidationErrorTemplate}"/>
    <Setter Property="gs:TextBoxExtensions.IsDirtyEnabled" Value="True" />
    <Style.Triggers>
        <Trigger Property="gs:TextBoxExtensions.ShowErrorTemplate" Value="false">
            <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
        </Trigger>
    </Style.Triggers>
</Style>

对于一件简单的事情来说,这似乎太多的代码了,但是对于我正在使用的所有文本框,我只需要做一次

问候,,
尼尔万

在显示视图后尝试设置数据上下文


对我来说,这很有帮助。

不,我不会抛出任何异常。我正在使用IDataErrorInfo接口来验证模型属性。我记得我必须使用ValidationRules只在集合上进行错误检查。很抱歉,我现在无法访问该代码。无论如何,感谢您的努力。这肯定会在视图中隐藏错误,可能是一个可行的解决方案。不过,我仍将等待一段时间,以防有比此更好的解决方案。谢谢这个问题:@AlexKofman将这个问题标记为重复。我已经做过了。Nirvan的解决方案可以做到这一点,如果你将代码移动到一个基类(例如BaseControll),那么你就可以从这个基类派生所有控件,并在所有控件中都有这种行为。我知道这已经有一段时间了,但我面临着同样的问题。您的解决方案工作得很好,我的问题是验证错误消息是否对所有字段都是相同的——错误模板指向静态资源——谢谢!