Question

I'm having trouble trying to figure out the best way to implement IDataErrorInfo in my WPF application. I have a few models, each with a lot of properties, that are being used. The ViewModel has Properties of each of these models and the View uses these properties to bind to the model. This is a reduced version of the structure I have:

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

My questions is - Where do I implement IDataErrorInfo - In the ViewModel or in the Model? The View binds to these properties as modelA.PropertyA1 and so on so the errors are raised in the Models and not in the ViewModel which makes it necessary to implement IDataErrorInfo in the Models. However, I've heard that it's a good practice to implement validation logic in the ViewModel.

I was wondering if there was a way to catch the errors in the ViewModel without writing a wrapper for each of the properties that would raise an error as there are lots of properties and writing a wrapper for each of them would be tedious.

Thanks for your help!

Was it helpful?

Solution 3

Thank you for your help guys! Here's how I decided to solve my problem:

I created two base classes, one for normal models (Ones that don't have any validations. It only implements INotifyPropertyChanged) and another for models that have validations as shown below.

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
}

Now my models looked like this:

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

Not a huge change there. The ViewModel now looks like this:

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

This seems to be working for me so far. This way, any new models that have validation need only derive from ValidationModelBase and have the ViewModel add an event handler for the validation event.

If anyone has a better way of solving my problem, do let me know - I'm open to suggestions and improvements.

OTHER TIPS

I think you should implement IDataErrorInfo in the view-model. If you have a base class for your view-models, and you probably should, you can implement it there. Now, all your implementation/validation-logic is in your base class and not spread amongst n-number of view-models.

You want a Valaidation of an Property of an Model this can only be done if you are implement in a Base class or for each Model in the model. If you want to Validate ModelA in ViewModel you need to impliment it in ViewModel but if you want to Implement a Validation for A1 you are need to Implement it in ModelA.

If you change the instance of modelA, IDataViewModel will go into the class and try to call (Instance of your ViewModel)["modelA"]. OK but this is not what you want, if you change a property of modelA IDataViewModel will go into the Instance of modelA and call modelA["B1"], and if you are now implement your validation in ViewModel, modelA will retrun an Empty string

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top