2010-04-07 119 views
4

我正在創建一個WPF應用程序,該應用程序將使用我的業務對象實現的IDataErrorInfo數據驗證。我一直在使用this demo from a blog post來了解ValidatesOnDataErrorsIDataErrorInfo:驗證頁面提交

該演示是一個簡單的應用程序,它將幾個文本框綁定到Contact對象,並在數據綁定中使用ValidatesOnDataErrors=True實現IDataErrorInfo驗證。爲了有效,文本框必須至少有五個字符。

這是我的問題:在演示中,只要文本框丟失焦點,就會觸發驗證。事實上,當應用程序啓動時,文本框會初始化爲無效狀態(紅色邊框)。我的應用程序必須暫停驗證,直到用戶單擊確定按鈕提交頁面。那時,文本框應該被驗證,並且如果無效,則將其置於錯誤狀態。

那麼,我將如何推遲對文本框的驗證,直到用戶單擊確定按鈕?謝謝你的幫助。

回答

0

數據綁定具有UpdateSourceTrigger屬性。顧名思義,它指定何時更新綁定的來源。對於Text屬性,默認情況下它被設置爲LostFocus。您可以將其設置爲Explicit,並在代碼中調用BindingExpression的UpdateSource方法。另一方面,您也可以推遲PropertyChanged事件的引發。然而,我認爲這些並不能解決應用程序啓動時的驗證問題。希望這有助於某種方式。

+0

這是一個部分的解決方案 - 我的數據綁定不會更新,直到我提交。不過,我很欣賞這個幫助,所以這一切都由我來完成。我在下面詳細描述了一個更復雜的解決方案,它使綁定保持同步,但將推遲直到頁面提交。 – 2010-04-07 12:30:56

7

感謝邁克爾的幫助。不幸的是,我需要綁定來保持不斷同步,只有延遲驗證。否則,邁克爾的解決方案將完成這項工作。所以,我走了一個稍微不同的方向。這是我最終實施的解決方案。

簡單演示:讓我們從最簡單的案例開始:我的業務對象實現IDataErrorInfo;讓我們假設我可以修改它的實現方式。我給每個業務對象一個額外的布爾屬性ValidationEnabled,我修改IDataErrorInfo實現總是返回一個空結果,如果該屬性爲false。

我在原始文章中提到的演示使用了具有兩個屬性的Contact對象;名字和姓氏。我添加了一個ValidationEnabled屬性和修改IDataErrorInfo實施看起來是這樣的:

#region IDataErrorInfo Members 

public string Error 
{ 
    get { throw new System.NotImplementedException(); } 
} 

public string this[string columnName] 
{ 
    get 
    { 
     // Initialize 
     string result = null; 

     // Perform validation only if enabled 
     if (ValidationEnabled) 
     { 
      switch (columnName) 
      { 
       // Validate 'First Name' 
       case "FirstName": 
        if (string.IsNullOrEmpty(FirstName)) 
        { 
         result = "First name has to be set"; 
        } 
        else if(FirstName.Length < 5) 
        { 
         result = "First name must be at least five characters"; 
        } 
        break; 

       // Validate "Last Name" 
       case "LastName": 
        if (string.IsNullOrEmpty(LastName)) 
        { 
         result = "Last name has to be set"; 
        } 
        else if (LastName.Length < 5) 
        { 
         result = "Last name must be at least five characters"; 
        } 
        break; 
      } 
     } 

     // Set return value 
     return result; 
    } 
} 

#endregion 

在我的版本的簡單的演示,我提交按鈕連接到事件處理程序中的代碼隱藏,使驗證和刷新綁定兩個文本框:

private void OnButtonClick(object sender, RoutedEventArgs e) 
{ 
    var contact = (Contact) DataContext; 
    contact.ValidationEnabled = true; 
    var binding = FirstNameBox.GetBindingExpression(TextBox.TextProperty); 
    binding.UpdateSource(); 
    binding = LastNameBox.GetBindingExpression(TextBox.TextProperty); 
    binding.UpdateSource(); 
} 

現在,只有在我嘗試提交表單時,纔會顯示紅色輪廓。

真實世界:在我的生產應用程序中,我不控制業務對象,也無法像我在簡單演示中那樣修改它們。因此,我爲業務對象創建了一個簡單的傳遞包裝器,該包裝器將屬性公開爲視圖的數據綁定並將這些屬性鏈接到包裝後的業務對象的相應屬性。包裝器實現IDataErrorInfo幷包含ValidationEnabled屬性。

如果未啓用驗證,則包裝的IDataErrorInfo實現始終返回null。如果啓用了驗證,那麼包裝將調用包裝對象上的IDataErrorInfo實現,並返回它從那裏獲取的內容。

任何使用Model-View-ViewModel模式的人都會熟悉這種方法。我們正在爲業務對象創建視圖模型包裝器,這被許多開發人員視爲MVVM的最佳實踐。它從業務模型關注點(簡單對象驗證)中分離出UI關注點(阻塞紅色邊框直到頁面被提交)。

此外,我的產品應用程序不會在代碼隱藏中使用事件處理程序。每MVVM,該按鈕將連接到一個ICommand,它將包含簡單演示中的OnButtonClick()處理程序的邏輯。

我希望這有助於任何人研究這個問題的道路。

+0

非常感謝...對我來說工作得非常好。 – danjarvis 2011-09-08 17:48:47