0

I am after how I could get the string from the IDataErrorInfo.this[string propertyName] method from my ViewModel.

basically, I have created a new property inside the model so I could validate each row in the model collection, and on my vaildation check, I will say if its valid or not and if not, it will disable the command in my viewmodel

Model

   string IDataErrorInfo.this[string propertyName]
    {
        get
        {
            // Vaildation logic

            if (result != string.Empty)
            {
                IsValid = false;
            }
            else
            {
                IsValid = true;
            }

            return result;
        }

ViewModel

    public bool CanSave
    {
        get
        {
            if (m_ProductVersion != null && m_ProductVersion.ProductItems != null)
            {
                foreach (ProductItem item in m_ProductVersion.ProductItems)
                {
                    // I dont want to use isValid any more
                    if (!item.IsValid)
                        return false;
                }
            }

            return true;
        }
    }

But I would like to get rid of the isValid Property if I can and use the result from the IDataErrorInfo inside the viewmodel.

Can this be done?

Thanks

user3428422
  • 4,300
  • 12
  • 55
  • 119

2 Answers2

2

First of all note, that your IsValid isn’t working correctly. Imagine you have 3 properties which you want to validate: A, B and C. WPF usually evaluates IDataErrorInfo whenever you enter something, so imagine I enter something invalid for A and B. I get an error and IsValid will be false. So far so good. Now, I enter something valid for C. A and B are still invalid, but IsValid will now be true—because the last IDataErrorInfo check yielded an empty result.

So your IsValid only checks the last property that was validated, which is definitely not enough for a general validity check.

A propert IsValid should run the validation for every property before returning a result. Something like this:

public bool IsValid ()
{
    for (string propertyName in allPropertyNames)
    {
        if (!string.IsEmptyOrNull(((IDataErrorInfo)this)[propertyName]))
            return false;
    }
    return true;
}

You need to maintain a list of all property names so we can iterate through those. Then we delegate the validation to this[propertyName] which calls the IDataErrorInfo validation. If we get any error, the object is not valid.

So, as you can see, you can replace a single property check with simply calling the IDataErrorInfo item property, but you usually want to do a check for all properties.

poke
  • 369,085
  • 72
  • 557
  • 602
2

I suspect that you have implemented the IDataErrorInfo interface incorrectly. Please take a look at my answer to the long-titled WPF command binding with input validation - how to enable the “save” button only if all input is valid question on Stack Overflow for an example. Having set up the interface in this way (you can ignore the additional properties 'Errors', etc.), then you can access the error string simply like this:

string error = dataItem.Error;

If you extend the functionality of the interface like my example shows, then you could handle multiple errors and you could do this:

ObservableCollection<string> errors = dataItem.Errors;

Or this:

public bool CanSave
{
    get { return !dataItem.HasErrors; }
}
Community
  • 1
  • 1
Sheridan
  • 68,826
  • 24
  • 143
  • 183
  • With this setup what are you doing to cause the errors collection to update/repoll itself when one of the validated controls has its value modified? – Dan Is Fiddling By Firelight Oct 28 '16 at 19:06
  • Hi @DanNeely, look at my linked answer. Each time the `Error` property is called, it checks the `HasErrors` property, which calls the `Errors` property, which kicks off the whole validation process again. Alternatively, you can just notify of property changes to the `Errors` collection from each property being validated (in addition to each property). – Sheridan Oct 31 '16 at 09:36