在Model V / s ViewModel中使用IDataErrorInfo

时间:2013-01-11 15:28:14

标签: wpf idataerrorinfo

我在试图找出在我的WPF应用程序中实现IDataErrorInfo的最佳方法时遇到了麻烦。我有几个模型,每个都有很多属性,正在使用。 ViewModel具有每个模型的属性,View使用这些属性绑定到模型。这是我所拥有的结构的简化版本:

public class ModelA
{
    public string PropertyA1 {get; set;}
    public string PropertyA2 {get; set;}
}

public class ModelB
{
    public string Property B1 {get; set;}
    public string Property B2 {get; set;}
}

public class ViewModel
{
    public ModelA modelA {get; set;}
    public ModelB modelB {get; set;}
}

我的问题是 - 我在哪里实现IDataErrorInfo - 在ViewModel或模型中? View将这些属性绑定为modelA.PropertyA1,依此类推,因此错误在模型中而不是在ViewModel中引发,这使得必须在模型中实现IDataErrorInfo。但是,我听说在ViewModel中实现验证逻辑是一种很好的做法。

我想知道是否有办法捕获ViewModel中的错误而不为每个可能引发错误的属性编写包装器,因为有很多属性并且为每个属性编写包装器会很繁琐。

感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

我认为你应该在视图模型中实现IDataErrorInfo。如果你有一个视图模型的基类,你可能应该,你可以在那里实现它。现在,您的所有实现/验证逻辑都在您的基类中,而不是在 n - 视图模型中传播。

答案 1 :(得分:1)

您希望对模型属性进行Valaidation,只有在Base类中实现或模型中的每个Model时才能实现。如果要在ViewModel中验证ModelA,则需要在ViewModel中实现它,但如果要实现A1的验证,则需要在ModelA中实现它。

如果更改modelA的实例,IDataViewModel将进入该类并尝试调用(ViewModel的实例)[“modelA”]。好的,但这不是你想要的,如果你改变了modelA的属性,IDataViewModel将进入modelA的实例并调用modelA [“B1”],如果你现在在ViewModel中实现验证,modelA将返回一个空字符串

答案 2 :(得分:0)

感谢您的帮助!以下是我决定解决问题的方法:

我创建了两个基类,一个用于普通模型(一个没有任何验证。它只实现了INotifyPropertyChanged),另一个用于具有验证的模型,如下所示。

public abstract class ModelBase : INotifyPropertyChanged
{
    //Implement INotifyPropertyChanged here
}

public delegate string ValidateProperty(string propertyName);

public abstract class ValidationModelBase : ModelBase, IDataErrorInfo
{
    private bool _canValidate;
    public bool CanValidate
    {
        get { return _canValidate; }
        set { _canValidate = value; }
    }

    #region IDataErrorInfo Members

    public string Error
    {
        get { return string.Empty; }
    }

    public string this[string columnName]
    {
        get
        {
            if (this.CanValidate)
            {
                return this.Validate(columnName);
            }
            return string.Empty;
        }
    }

    #endregion

    #region Validation Section

    public event ValidateProperty OnValidateProperty;

    public string Validate(string propertyName)
    {
        if (this.OnValidateProperty != null)
        {
            return OnValidateProperty(propertyName);
        }
        return string.Empty;
    }

    #endregion
}

现在我的模特看起来像这样:

public class ModelA : validationModelBase
{
    public string PropertyA1 {get; set;}
    public string PropertyA2 {get; set;}
}

public class ModelB : ValidationModelBase
{
    public string Property B1 {get; set;}
    public string Property B2 {get; set;}
}

那里没有太大的变化。 ViewModel现在看起来像这样:

public class ViewModel
{
    public ModelA modelA {get; set;}
    public ModelB modelB {get; set;}

    public ViewModel()
    {
        this.modelA.OnValidateProperty += new ValidateProperty(ValidateModelA);
        this.modelB.OnValidateProperty += new ValidateProperty(ValidateModelB);
    }

    private string ValidateModelA(string propertyName)
    {
        //Implement validation logic for ModelA here
    }    

    private string ValidateModelB(string propertyName)
    {
        //Implement validation logic for ModelB here
    }
}

到目前为止,这似乎对我有用。这样,任何具有验证的新模型都只需要从ValidationModelBase派生,并让ViewModel为验证事件添加事件处理程序。

如果有人有更好的方法来解决我的问题,请告诉我 - 我愿意接受建议和改进。