IsValid not updating when property change causes broken rule

IsValid not updating when property change causes broken rule

Old forum URL: forums.lhotka.net/forums/t/10311.aspx


Jaans posted on Thursday, April 28, 2011

I know the IsDirty / IsValid / IsXXX issue has been discussed before ( http://forums.lhotka.net/forums/t/7143.aspx )  and the "work around" has changes to the ViewModelBase to "hook" and listen for changes and re-expose them. There is also a pending feature request.

The following however is not addressed by the above:

The above workaround is fine for when you are dealing with IsValid state at the "root" level of your object tree/graph and you are interested if anything is causing the object to be invalid.

Where I'm running into real frustration is when I need to respond to a change to the IsValid property for a Child Object. Specifically my Business object graph is an Editable Root composing an Editable Child List of Editable Children.
ER --> ECL (EC)

In this case, IsValid on the ViewModel (which is bound to the Root object) is updating just fine (thanks to the workaround above). My problem is that I need it for each individual child, in order to give visual feedback to the user about the list of children and which of those are invalid.

In the Xaml I have a DataGrid that is bound to the Child List property of the root. And inside the grid I have a custom template column that contains some arbitary control that is bound to the IsValid property of the current child in the list:

<TextBlock Text="Invalid" Visibility="{Binding IsValid, Converter={StaticResource InvisibilityConverter}}" />

I'm not sure what the real issue is with the backwards compatibilty with Windows Forms binding, but could we not make the IsXXXX properties work like proper properties and raise property change events for them?

Thanks

ddredstar replied on Thursday, April 28, 2011

have you tried BusinessRules.CheckRules(); when you retrieve you Child object?

Jaans replied on Thursday, April 28, 2011

Not quite relevant.

Perhaps I should have elaborated more. There is a business rule associated with a property, and when that property is changed such that it breaks the validation rule, the particular child is no longer valid. Therefore the IsValid should raise a property changed so that Silverlight XAML binding can repond to it.

Now, if you requery the property IsValid directly it'll give you the correct value, problem is that the property changed isn't "triggered" for it and XAML binding doesn't see it.

Sorry, I hope that clear it up some...

JonnyBee replied on Thursday, April 28, 2011

Hi Jaans,

I'm not so sure that we should break DataBinding for WindowsForms in Csla yet, so one possible workaround for you is to add: 

    protected override void OnValidationComplete()
    {
        base.OnValidationComplete();
 
        OnPropertyChanged("IsValid");
        OnPropertyChanged("IsSelfValid");
    } 

 to your Child editable object which will make sure to always update the IsValid and IsSelfValid after validation is completed.

Jaans replied on Thursday, April 28, 2011

Thanks Jonny!

Now that's a nice an simple solution and it works like a bomb (already tested it).
It's so simple, I'm wondering why I couldn't think of it Tongue Tied

I agree, we shoudn't break WindowsForms (still very current - and we ourselves have quite a few active systems using Windows Forms). I wasn't proposing that we break it, but wondering whether the Csla AppSetting for PropertyChangeMode (Xaml / Windows) could be leveraged to make sure that for Xaml, it just works.

Looking at your workaround above, might it be something we would like to see added to the CSLA code base? Would that break WindowsForms? If so, we could put it inside an conditional statement that looks at the current ApplicationContext.PropertyChangeMode.

Thanks again,
Jaans

JonnyBee replied on Thursday, April 28, 2011

Hi Jaans,

Yes - it would not be as windows forms databinding expects but adding a conditional statement that looks at ApplicationContext.PropertyChangedMode should work just fine.

For a starter - I'd rather add it to my own intermediate base classes.

We might do this in the csla codebase but that's really up to Rocky to decide on.

ajj3085 replied on Thursday, April 28, 2011

Jaans, are you doing MVVM?  I had thought that the IsXXX properties behave as you expect if you bind them to the ones exposed in ViewModel<T> from Csla.xaml.

Jaans replied on Thursday, April 28, 2011

@Andy

Yes I'm doing MVVM and yes you are right, the IsXXX properties on the ViewModel (which re-exposes the same properties from the BO) does work. That's not the issue - the issue is that the ViewModel (can) only re-exposes the root parent object's IsXXX properties and what I needed to "just work" was the IsXXX properties on Child objects.

Think: ViewModel.Model.EditbleRoot.ChildList[0].Child.IsValid

@Jonny and @Rocky

Thanks - an intermediate base class is a temporary alternative.

To me if it seems a bit like "broken" behaviour for CSLA to not raise property change events for properties that effectively have changed

Ah... Rocky's post just came though before I finished this reply: 

Thanks again gents!

RockfordLhotka replied on Thursday, April 28, 2011

There is a potential perf impact. There's no harm in you trying the idea in this thread, and if the perf issue doesn't cause you trouble then life is good :)

RockfordLhotka replied on Thursday, April 28, 2011

Jaans

Looking at your workaround above, might it be something we would like to see added to the CSLA code base? Would that break WindowsForms? If so, we could put it inside an conditional statement that looks at the current ApplicationContext.PropertyChangeMode.

Yes, I would like to do this in a future release.

There's a little more to it, in terms of making things efficient. Right now IsValid and IsDirty are calculated on each get - they aren't maintained as fields, and so it isn't practical right now to only raise the changed event when they actually change. Even adding a simple last-value field to solve that wouldn't be entirely ideal, because each changed event causes the getter to be invoked (possibly multiple times).

Not that all this can't be addressed - I'm just observing that the correct solution is a bit more complex than a simple on-off solution.

Copyright (c) Marimer LLC