下面是ViewModel基類的ValidationErrors屬性的代碼。我們的視圖模型基類實現INotifyPropertyChanged和IDataErrorInfo,並且對於Silverlight 4+還有INotifyDataErrorInfo。
請注意Silverlight和WPF的條件編譯語句。對於Silverlight,我們只需使用標準的INotifyDataErrorInfo機制通知視圖,對於WPF,我們觸發PropertyChanged事件來刷新受影響的控件。
這個用法很簡單。每個派生視圖模型類只需要設置ValidationErrors屬性,其他所有內容都由屬性設置器處理。 ValidationFailure失敗類屬於我們用來實現實際驗證邏輯的FluentValidation庫。
public IList<ValidationFailure> ValidationErrors
{
get { return GetPropertyValue(() => ValidationErrors); }
protected set
{
List<string> obsoleteValidationErrors = null;
// collect names of properties that do not longer have errors
#if SILVERLIGHT
if (ErrorsChanged != null)
#else
if (PropertyChanged != null)
#endif
{
var oldErrorsCollection = ValidationErrors != null && ValidationErrors.Count > 0 ? ValidationErrors : new List<ValidationFailure>();
var newErrorsCollection = value != null && value.Count > 0 ? value : new List<ValidationFailure>();
var newPropertyNames = newErrorsCollection.Select(x => x.PropertyName).Distinct().ToDictionary(x => x);
// figure out which errors are no longer part of the new validation error collection
obsoleteValidationErrors = oldErrorsCollection.Where(x =>
!newPropertyNames.ContainsKey(x.PropertyName)).Select(x => x.PropertyName).Distinct().ToList();
}
if (SetPropertyValue(() => ValidationErrors, value))
{
// fire event for properties that do not longer have errors
if (obsoleteValidationErrors != null)
{
foreach (var obsoleteValidationErrorPropertyName in obsoleteValidationErrors)
#if SILVERLIGHT
ErrorsChanged(this, new DataErrorsChangedEventArgs(obsoleteValidationErrorPropertyName));
#else
OnPropertyChanged(obsoleteValidationErrorPropertyName);
#endif
}
// fire event for properties that now have errors
#if SILVERLIGHT
if (value != null && ErrorsChanged != null)
#else
if (value != null && PropertyChanged != null)
#endif
{
var propertyNames = value.Select(x => x.PropertyName).Distinct().ToList();
foreach (var failedProperty in propertyNames)
#if SILVERLIGHT
ErrorsChanged(this, new DataErrorsChangedEventArgs(failedProperty));
#else
OnPropertyChanged(failedProperty);
#endif
}
}
}
}
爲此使用代碼隱藏並不違法。只需添加一點C#。 –