私が過去にこれを行った 1 つの方法は、 Model で ValidationDelegate を公開することです。これにより、ViewModel が独自の検証コードをモデルにアタッチできるようになります。
通常、これを行うのは、Model
レイヤーをプレーン データ オブジェクトとして使用するためです。そのため、モデルは max-length や not-null などの基本的なことのみを検証し、データ モデルに固有ではない高度な検証は ViewModel で行われます。これには通常、アイテムが一意であること、ユーザーが特定の範囲に値を設定する権限を持っていること、または特定のアクションに対してのみ検証が存在する場合のようなものが含まれます。
public class CustomerViewModel
{
// Keeping these generic to reduce code here, but it
// should include PropertyChange notification
public AddressModel Address { get; set; }
public CustomerViewModel()
{
Address = new AddressModel();
Address.AddValidationDelegate(ValidateAddress);
}
// Validation Delegate to validate Adderess
private string ValidateAddress(object sender, string propertyName)
{
// Do your ViewModel-specific validation here.
// sender is your AddressModel and propertyName
// is the property on the address getting validated
// For example:
if (propertyName == "Street1" && string.IsNullOrEmpty(Address.Street1))
return "Street1 cannot be empty";
return null;
}
}
検証デリゲートに通常使用するコードは次のとおりです。
#region IDataErrorInfo & Validation Members
#region Validation Delegate
public delegate string ValidationDelegate(
object sender, string propertyName);
private List<ValidationDelegate> _validationDelegates =
new List<ValidationDelegate>();
public void AddValidationDelegate(ValidationDelegate func)
{
_validationDelegates.Add(func);
}
public void RemoveValidationDelegate(ValidationDelegate func)
{
if (_validationDelegates.Contains(func))
_validationDelegates.Remove(func);
}
#endregion // Validation Delegate
#region IDataErrorInfo for binding errors
string IDataErrorInfo.Error { get { return null; } }
string IDataErrorInfo.this[string propertyName]
{
get { return this.GetValidationError(propertyName); }
}
public string GetValidationError(string propertyName)
{
string s = null;
foreach (var func in _validationDelegates)
{
s = func(this, propertyName);
if (s != null)
return s;
}
return s;
}
#endregion // IDataErrorInfo for binding errors
#endregion // IDataErrorInfo & Validation Members