ReactiveValidatedObject and depending properties

338 views
Skip to first unread message

Lukas Cenovsky

unread,
May 4, 2011, 7:12:53 PM5/4/11
to reacti...@googlegroups.com
Hi,
what is the recommended approach for validating two properties depending
one on the another?

Classical example is start and end date:
- user enters start "6th"
- user enters end "3rd" - both fields are invalid
- user corrects start to "1st" - both fields should be ok

How can ReactiveValidatedObject help here?

--
-- Lukáš

Paul Betts

unread,
May 5, 2011, 12:09:42 PM5/5/11
to reacti...@googlegroups.com
ReactiveUI includes a new validation attribute, "ValidatesViaMethod"
that should make this fairly straightforward. Tag the Foo property
with [ValidatesViaMethod], then create a method in your class called
IsFooValid (you can override the convention-based naming in the
attribute).

--
Paul Betts <pa...@paulbetts.org>

2011/5/4 Lukas Cenovsky <ceno...@bakalari.cz>:

Lukas Cenovsky

unread,
May 5, 2011, 1:10:33 PM5/5/11
to reacti...@googlegroups.com
I have found the [ValidatesViaMethod] attribute. It looked promising but the problem is rather with error setting to the controls - when Foo and Bar are invalid because Foo is greater than Bar and I fix Bar, the error disappears only from Bar and remains in Foo.

I'll probably will have to implement IDataError by myself anyway because I need to combine client and server (e.g. "email is already registered") validations.

--
-- Lukáš

Lukas Cenovsky

unread,
May 6, 2011, 8:50:36 AM5/6/11
to reacti...@googlegroups.com
Paul,
I'm looking into Validate.cs and I cannot get how you update _validationCache when property value changes.

Currently, my idea is to have a method on ReactiveValidatedObject which would perform the whole object validation and set errors for properties. I want to fill errors into _validationCache (or any backing structure behind public string this[string columnName] and call raisePropertyChanged for all invalid properties.

--
-- Lukáš

Lukas Cenovsky

unread,
May 6, 2011, 9:51:23 AM5/6/11
to reacti...@googlegroups.com
Aah - I see it now - it's in the constructor :-)

--
-- Lukáš

Lukas Cenovsky

unread,
May 6, 2011, 11:19:41 AM5/6/11
to reacti...@googlegroups.com
Let's say I have properties name and surname and these properties depend one on the other.

In the property setter, I do:

set {
    if (_name != value) {
        _name = value;
        raisePropertyChanged("name");
        raisePropertyChanged("surname");
    }
}

raisePropertyChanged("surname") is there to update its surname's validation. The validation is updated but immediately after that the Changed observable from the constructor is processed which deletes the validation error:
  1. the validation error is updated by this["surname"]
  2. the validation error is deleted from cache by object.Changed observable
The above behavior is caused by ReactiveObject.raisePropertyChanged:
protected internal void raisePropertyChanged(string propertyName)
{
    Contract.Requires(propertyName != null);
 
    verifyPropertyName(propertyName);
    this.Log().DebugFormat("{0:X}.{1} changed"this.GetHashCode(), propertyName);
 
    if (!areChangeNotificationsEnabled) {
        this.Log().DebugFormat("Suppressed change");
        return;
    }
 
    // HANDLER
    var handler = this.PropertyChanged;
    if (handler != null) {
        var e = new PropertyChangedEventArgs(propertyName);
        handler(this, e);
    }

    // OBSERVABLE
    notifyObservable(new ObservedChange<objectobject>() {
        PropertyName = propertyName, Sender = this, Value = null
    }, changedSubject);
}

When I switch HANDLER and OBSERVABLE, it works correctly. But I am afraid
I break something with such change...

So my idea from bellow does not work either because I don't have any way how to notify property about validation error (to refresh it in view) when I set it manually - calling raisePropertyChanged deletes it. Looks like I have to reimplement the ReactiveValidatedObject...

--
-- Lukáš

Paul Betts

unread,
May 6, 2011, 2:08:42 PM5/6/11
to reacti...@googlegroups.com
How are "Name" and "Surname" related in your model? Can the user edit
both independently? If so, why would both change when you update name?
You're right that properties whose values affect each other are
definitely tricky - one way you could solve this is by creating an
Output Property that CombineLatest's the two related properties (via
ToProperty), then do your validation on that property instead. This
doesn't work with Silverlight's UI validation hints though (since the
thing that's failing isn't a visible property), but it will show up in
a Validation Summary control.

--
Paul Betts <pa...@paulbetts.org>

2011/5/6 Lukas Cenovsky <ceno...@bakalari.cz>:

Lukas Cenovsky

unread,
May 6, 2011, 6:13:22 PM5/6/11
to reacti...@googlegroups.com
Yes, user can edit them separately. It was wrongly chosen example - better is start and end dates. The depending property has to "change" to update the bound control with error validation via IDataErrorInfo interface.

It's similar to situation when a result from server validation comes and I need to update properties  that are wrong (like the email address is already used).

I thought somebody have to have it solved already but apparently not... I have an idea which I'm going to try during the weekend.

--
-- Lukáš

Paul Betts

unread,
May 6, 2011, 8:18:01 PM5/6/11
to reacti...@googlegroups.com
In a case like this, I think that from a UX standpoint it's still a
better idea to combine the properties into a meaningful entity (like a
TimeSpan) then perform validation on that. Reason being, is that it's
really obnoxious when you're trying to set the properties one at a
time as a user, and the UI keeps "correcting" you - there's usually
going to be a time where the properties *are* incorrect while the user
fixes them up. Better to just disallow them to submit at the form
level (or object-level as it were) then to try to validate the
individual pieces.

Lukas Cenovsky

unread,
May 13, 2011, 4:16:12 AM5/13/11
to reacti...@googlegroups.com
I eventually implemented my own ReactiveValidatedObject which handles
depending properties and server validation. Anyway, thanks for the advices.

--
-- Lukáš

Reply all
Reply to author
Forward
0 new messages