1

Entity Framework 4.3でWPFとMVVMを使用するプロジェクトに取り組んでいますが、IDataErrorInfoインターフェイスを実装するビジネスロジック検証を実行する方法を知りたいです。

私のすべてのモデル(POCOクラス)は、maxlength、非負の数などの生の検証を実行するためにそれを実装しています...

しかし、レコードの重複を防ぐなど、ビジネスロジックの検証についてはどうでしょうか。

マテリアルの「参照」のテキストボックスがあるとします。これは一意である必要があり、次のように定義されています。

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

モデルは参照の長さを正常に検証しますが、ビューモデルのマテリアルobservablecollectionにすでにマテリアルがある場合、IDataErrorInfoメッセージを利用しながら、ViewModelからこの事実をユーザーに通知するにはどうすればよいですか?

4

1 に答える 1

2

私は過去に、ViewModelsが追加のビジネスロジック検証のためにフックできるモデルからの検証デリゲートを公開することによってこれを行いました

最終結果は次のようになります。

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;
    }
}

私のモデルのほとんどは、この検証デリゲートを含む汎用基本クラスを継承しています。これは、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

これにより、モデルで基本的なデータ検証を維持でき、ViewModelsはカスタマイズされたビジネスロジック検証をモデルにアタッチすることもできます。

于 2012-07-23T17:32:15.533 に答える