Search code examples
c#wpfmvvmcatel

Propagate validation from Model to View with Catel


I am working on a program using Catel's MVVM (4.0.0) implementation. I have a model class which as some business logic - it must observe a rule regarding one of it's properties values.

For example, let say I have a Trap class which has a TargetValue and a CurrentValue properties. For this class there is a rule that must enforce that the TargetValue property can only be less then or equal (<=) CurrentValue. (The CurrentValue is updated via some events in the system).

The traps are exposed to the user (I have a VM which holds a list of such traps and is bound to a data grid in the UI) where she can change TargetValue.

Initially I though to create a VM to wrap the Trap object instance and enforce the rule there but since the rule is actually related more to the model (or business logic, that is, I may need the same rule everywhere I use Trap class) I thought it better to implement it in the property setter for TargetValue (where I will check the validity of the new value and either reset or not change the underlying field value).

So supposedly I do it in the setter (is that even a correct implementation?) - is there a way to notify the VM (or UI directly) that there was a violation (for example by setting cell border color or something)?

I thought that maybe I can use the RaisePropertyChanging in collaboration with RaisePropertyChanged that ObservableObject exposes though it seems cumbersome.

Is there a proper way for such a pattern?

Thanks,

Tomer


Solution

  • Following the discussion regarding Catel's capabilities it seems that going through "regular" validation flow would not do the trick here due to the order of operations:

    • Property Setter
    • ValidateFields
    • Error info is ready for VM

    What the solution should be is as follows:

    • The CurrentValue property setter should be private so that it cannot be bound to (either directly or through the VM by using decorations etc
    • Add to the Trap class IDataErrorInfo (or INotifyDataErrorInfo) implementation
    • Implement a SetCurrentValue function which validates data and only sets it if legal. In case not, invoke IDataErrorInfo mechanism.
    • In the UI - bind to the function and not property (e.g. http://msdn.microsoft.com/en-us/library/aa348824(v=vs.110).aspx)

    This approach should answer the requirements above - the property value is never invalid in any use case but still it is possible to coordinate with the UI.