Validation in SubObject Causes IsDirty == true in ViewModel

Feb 7, 2012 at 12:12 AM

I think this may be a bug in how Catel handles Validation warnings and errors.  This is a bit complicated so bare with me:

I have a window which contains a listbox that displays a collection of custom items.  We will call them Person objects to make it simple.  There is a PersonUserControl and PersonViewModel that form the ItemTemplate for each Person in the listbox.  The window's ViewModel has an ObservableCollection<Person> property, which is automatically populated when the ViewModel is constructed.  The listbox ItemsSource is bound to this collection.

The problem comes in when Validate() is called on the Person objects.  If an error or warning is found, DataObjectBase.Validate(bool force, bool notifyChangedPropertiesOnly, bool validateDataAnnotations) calls RaisePropertyChanged("HasWarnings(Errors)").  This event gets captured by my Window's ViewModel in OnObjectPropertyChanged(), which again calls RaisePropertyChanged().  DataObjectBase.RaisePropertyChanged checks IsValidating to try to avoid setting IsDirty to true during validation.  However, at this point, the window's ViewModel.IsValidating property is false, because the VM is not validating, the Person object is. Therefore, IsDirty gets set to true on the VM, even though the user hasn't changed anything on the window yet.

Note that DataObjectBase.RaisePropertyChanged also checks the property name to see if it is a warning or error.  However, it only checks to see if the property name is WarningMessageProperty or ErrorMessageProperty.  These are constants that are set to "IDataWarningInfo.Warning" and "IDataErrorInfo.Error", respectively.  As mentioned above, the property name that is being passed to RaisePropertyChanged is "HasWarnings" or "HasErrors".  

I think the simple fix is to just change this line:

if (setDirtyAndAllowAutomaticValidation && !IsValidating &&
                (string.Compare(e.PropertyName, WarningMessageProperty) != 0) &&
                (string.Compare(e.PropertyName, ErrorMessageProperty) != 0))

 

To:

            if (setDirtyAndAllowAutomaticValidation && !IsValidating &&
                (string.Compare(e.PropertyName, WarningMessageProperty) != 0) &&
                (string.Compare(e.PropertyName, ErrorMessageProperty) != 0) &&
                (string.Compare(e.PropertyName, "HasErrors") != 0) &&
                (string.Compare(e.PropertyName, "HasWarnings") != 0))

 

This is line 2329 in DataObjectBase.cs in Catel 2.5 stable release source code.

Tom

 

Coordinator
Feb 7, 2012 at 7:45 AM

You are correct, we will fix this in the new version. Thanks for letting us know with so many details!

Feb 7, 2012 at 3:20 PM

Thanks for confirming.  BTW, do you prefer potential bugs to be reported here, or as an issue in the issue tracker?

Coordinator
Feb 7, 2012 at 3:32 PM

In the issue tracker, then we can provide a status and close it if solved. You can also attach demo projects or fixes (with unit tests), so that's preferred.

Coordinator
Feb 19, 2012 at 9:53 PM

The fix has just been applied.