我正在使用WPF和MVVM以及Entity Framework 4.3开展项目,我想知道如何执行实现IDataErrorInfo接口的业务逻辑验证。
我的所有模型(POCO类)都在实现它以执行原始验证,例如maxlength,非负数等等......
但是商业逻辑验证呢,比如防止重复记录?
想象一下,我有一个材料“参考”的文本框,它必须是唯一的,定义喜欢这样:
<TextBox Text="{Binding Material.Reference, ValidatesOnDataErrors=True, NotifyOnValidationError=true,
UpdateSourceTrigger=PropertyChanged}">
该模型将成功验证引用的长度,但是如果我的viewmodel的材质中已有一个材质observablecollection,我该如何从ViewModel通知用户这个事实,还是利用了IDataErrorInfo消息?
答案 0 :(得分:2)
我过去通过公开我的模型中的验证委托来完成此操作,我的ViewModel可以挂钩以进行其他业务逻辑验证
最终结果看起来像这样:
public class MyViewModel
{
// Keeping these generic to reduce code here, but they
// should be full properties with PropertyChange notification
public ObservableCollection<MyModel> MyCollection { get; set; }
public MyModel SelectedModel { get; set; }
public MyViewModel()
{
MyCollection = DAL.GetAllModels();
// Add the validation delegate to each object
foreach(var model in MyCollection)
model.AddValidationErrorDelegate(ValidateModel);
}
// Validation Delegate to verify the object's name is unique
private string ValidateObject(object sender, string propertyName)
{
if (propertyName == "Name")
{
var obj = (MyModel)sender;
var existingCount = MyCollection.Count(p =>
p.Name == obj.Name && p.Id != obj.Id);
if (existingCount > 0)
return "This name has already been taken";
}
return null;
}
}
我的大多数模型都继承自通用基类,其中包含此验证委托。以下是该基类的相关代码,取自我在Validating Business Rules in MVVM
上的博客文章#region IDataErrorInfo & Validation Members
/// <summary>
/// List of Property Names that should be validated.
/// Usually populated by the Model's Constructor
/// </summary>
protected List<string> ValidatedProperties = new List<string>();
#region Validation Delegate
public delegate string ValidationErrorDelegate(
object sender, string propertyName);
private List<ValidationErrorDelegate> _validationDelegates = new List<ValidationErrorDelegate>();
public void AddValidationErrorDelegate(
ValidationErrorDelegate func)
{
_validationDelegates.Add(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)
{
// Check to see if this property has any validation
if (ValidatedProperties.IndexOf(propertyName) >= 0)
{
string s = null;
foreach (var func in _validationDelegates)
{
s = func(this, propertyName);
if (s != null)
return s;
}
}
return s;
}
#endregion // IDataErrorInfo for binding errors
#region IsValid Property
public bool IsValid
{
get
{
return (GetValidationError() == null);
}
}
public string GetValidationError()
{
string error = null;
if (ValidatedProperties != null)
{
foreach (string s in ValidatedProperties)
{
error = GetValidationError(s);
if (error != null)
return error;
}
}
return error;
}
#endregion // IsValid Property
#endregion // IDataErrorInfo & Validation Members
这允许我在我的模型中保留基本数据验证,我的ViewModel也可以将他们想要的任何自定义业务逻辑验证附加到模型中。