2010-05-12 40 views
12

当我第一次向用户显示我的屏幕时,我宁愿没有在用户有机会填写任何表单域之前显示所有必填字段的验证消息。我已将UpdateSourceTrigger设置为绑定到LostFocus,但在第一次显示控件时仍会显示错误。有什么办法可以解决这个问题吗?如何让WPF在初次显示控件时不显示验证错误?

XAML:

<TextBox Text="{Binding Path=OpeningOdometer, ValidatesOnDataErrors=True, UpdateSourceTrigger=LostFocus}" /> 

视图模型:

[Required(ErrorMessage = "Please enter the opening odometer.")] 
[Range(0, Double.MaxValue, ErrorMessage = "Opening Odometer must be a positive number")]   
public string OpeningOdometer 
{ 
    get { return _openingOdometer; } 
    set 
    { 
     _openingOdometer = value; 
     NotifyOfPropertyChange(() => OpeningOdometer); 
    } 
} 

// Implementation of IDataErrorInfo 
public string this[string columnName] 
{ 
    get 
    { 
     // This uses the System.ComponentModel.DataAnnotations placed on 
     // the OpeningOdometer property to produce an error string 
     // if the value of the property is in violation of any of the 
     // annotated rules. 
     return _valHelper.GetErrorsForProperty(columnName, this); 
    } 
} 
+1

你有没有为这个Brian制定出最好的方法? :\ – GONeale 2012-08-16 01:17:31

回答

2

您可以得到更好的答案,如果你作出努力来发表您的相关代码/ XAML的一个片段。这将使复制和消除大部分猜测变得更容易。

尝试在您的验证规则上设置ValidatesOnTargetUpdated="False",看看是否有帮助。

+2

我实际上没有使用ValidationRules,我正在实现IDataErrorInfo。应该在问题中包含更多细节,道歉。 – 2010-05-13 14:28:59

8

我不把验证逻辑放在索引器中。这将把验证的时间控制在视图上。在你的方案中,每当请求属性的错误信息时,视图就会触发验证。我不知道会发生什么情况,我敢打赌你也不会。

相反,我在其setter中放置了一个属性的验证逻辑(更准确地说,是对验证函数的调用)。我将错误消息存储在键入属性名称的字典中,并让索引器查找属性的错误消息。

默认情况下,错误消息是最新的属性的当前值。每当视图更新一个属性并请求其新的错误信息时,它就会得到正确的答案。

但是你对字典中的实际内容也有非常细致的控制。如果你想让一个属性在UI中显示为有效,只需清除它在字典中的错误信息(并且提升PropertyChanged,这样UI就知道会得到新的错误信息)。或者,当您构建视图模型对象时,您可以设置属性的支持字段而不是属性本身,绕过验证。

2

只是为了表明这一点利用IDataErrorInfo我如何处理......

我把调用一个在我看来绑定属性的每个setter方法称为OnDataUpdated()新的方法,如:

private string username; 
    public string Username 
    { 
     get { return username; } 
     set 
     { 
      username = value; 
      OnDataUpdated(); 
     } 
    } 

    private string password; 
    public string Password 
    { 
     get { return password; } 
     set 
     { 
      password = value; 
      OnDataUpdated(); 
     } 
    } 

然后里面OnDataUpdated()马克私有字段作为布尔表示true数据已经改变的第一次(FormType只需要为自己的公司情况):

private void OnDataUpdated() 
{ 
    dataChanged = true; 
    // .. Any other universal RaisePropertyChanged() events you may want to call to get your UI into sync. Eg. RaisePropertyChanged(() => CanConfirm); 
} 

然后在我的IDataErrorInfo索引器属性中,我执行以下操作(我将其分开,以便可以手动调用'ValidForm()'以执行表单验证。

public string this[string columnName] 
     { 
      get 
      { 
       string result = null; 
       if (columnName == "Username") 
       { 
        // If other payment amounts have fully paid for balance, and cash amount has been entered, deny 
        if (!ValidForm(FormType.Step1, columnName)) 
         result = "Please enter the username field."; 
       } 
       else if (columnName == "Password") 
       { 
        if (!ValidForm(FormType.Step1, columnName)) 
         result = "Please enter the password field."; 
       } 
       return result; 
      } 
     } 

     /// <summary> 
     /// Test if valid form. 
     /// </summary> 
     /// <param name="formType">Specify which form we should validate.</param> 
     /// <param name="columnName">If ommitted, entire form will be validated.</param> 
     /// <returns></returns> 
     private bool ValidForm(FormType formType, string columnName = null) 
     { 
      // This field is used to denote when data has changed on the form. 
      // If data has changed, we know we can activate any form validation. 
      // We do not activate the form validation until after a user has typed 
      // something in at least. 
      if (!dataChanged) return true; 

      var errors = false; 
      if (formType == FormType.Step1 && ((string.IsNullOrEmpty(columnName) || columnName == "Username") && string.IsNullOrEmpty(Username))) 
       errors = true; 
      if (formType == FormType.Step1 && ((string.IsNullOrEmpty(columnName) || columnName == "Password") && string.IsNullOrEmpty(Password))) 
       errors = true; 
      return !errors; 
     } 

工程很漂亮。现在我只有在用户编辑表单后才会出现验证样式。

如果你想在蛋糕上一​​些额外的结冰,你可以在我的RaisePropertyChanged(() => CanConfirm);OnDataUpdated()方法发表意见,并结合,为您的确认按钮IsEnabled={Binding CanConfirm}与关联的属性:

/// <summary> 
/// Can the user confirm step 1? 
/// </summary> 
public bool CanConfirm 
{ 
    get { return ValidForm(FormType.Step1); } 
} 

和您的按钮才可当你的表单也有效时启用。 :)

享受!并且与WPF这个庞然大物一样好运。