使用Entity Framework和IDataErrorInfo进行业务逻辑验证

时间:2012-07-23 16:58:37

标签: wpf entity-framework validation mvvm idataerrorinfo

我正在使用WPF和MVVM以及Entity Framework 4.3开展项目,我想知道如何执行实现IDataErrorInfo接口的业务逻辑验证。

我的所有模型(POCO类)都在实现它以执行原始验证,例如maxlength,非负数等等......

但是商业逻辑验证呢,比如防止重复记录?

想象一下,我有一个材料“参考”的文本框,它必须是唯一的,定义喜欢这样:

 <TextBox Text="{Binding Material.Reference, ValidatesOnDataErrors=True, NotifyOnValidationError=true, 
                                 UpdateSourceTrigger=PropertyChanged}">

该模型将成功验证引用的长度,但是如果我的viewmodel的材质中已有一个材质observablecollection,我该如何从ViewModel通知用户这个事实,还是利用了IDataErrorInfo消息?

1 个答案:

答案 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也可以将他们想要的任何自定义业务逻辑验证附加到模型中。