感謝邁克爾的幫助。不幸的是,我需要綁定來保持不斷同步,只有延遲驗證。否則,邁克爾的解決方案將完成這項工作。所以,我走了一個稍微不同的方向。這是我最終實施的解決方案。
簡單演示:讓我們從最簡單的案例開始:我的業務對象實現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()處理程序的邏輯。
我希望這有助於任何人研究這個問題的道路。
這是一個部分的解決方案 - 我的數據綁定不會更新,直到我提交。不過,我很欣賞這個幫助,所以這一切都由我來完成。我在下面詳細描述了一個更復雜的解決方案,它使綁定保持同步,但將推遲直到頁面提交。 – 2010-04-07 12:30:56