2010-05-12 46 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這個龐然大物一樣好運。