ValidationRules - multiple conditions

ValidationRules - multiple conditions

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


gajit posted on Friday, October 20, 2006

Hi guys,

A simple one I hope.

I need to create a validation rule on my object that is dependent on the value of a number of columns in my object.

Here's what I have;

Protected Overrides Sub AddBusinessRules()

ValidationRules.AddRule(AddressOf Validation.CommonRules.StringRequired, "SALESREP")

ValidationRules.AddRule(AddressOf QuantitySpecified, "ACCOUNTS")

ValidationRules.AddRule(AddressOf QuantitySpecified, "UNITS")

ValidationRules.AddRule(AddressOf QuantitySpecified, "UNITVALUE")

ValidationRules.AddRule(AddressOf QuantitySpecified, "ORDERVALUE")

End Sub

Private Function QuantitySpecified( _

ByVal target As Object, _

ByVal e As Validation.RuleArgs) As Boolean

If mACCOUNTS < 1 AndAlso mUNITS < 1 AndAlso mUNITVALUE < 1 AndAlso mORDERVALUE < 1 Then

e.Description = "You must specify at least one 'quantity' criteria"

Return False

End If

e.Description = ""

Return True

End Function

#End Region

The problem here is that initially (all values are zero) the rules are broken, and even though I may say, change the ACCOUNTS value to 100, it doesn't remove the other broken rules.

Similar, if I only create a single rule on Accounts, it is only triggered when changing that value and no others.

My thinking is that I create another private property called 'mtotal' and write it each time any of the other values changes. But I wanted to see if there was another (proper) way of addressing this before I proceeded.

Any suggestions?

 

Thanks,

gajit.

 

 

 

 

JoeFallon1 replied on Friday, October 20, 2006

Change AndAlso to OrElse and see what happens.

Joe

 

skagen00 replied on Friday, October 20, 2006

On page 414 of the C# book it talks about solving dependant properties.

In your setter of each amount, you would:

ValidationRules.CheckRules("<propertyx>");

ValidationRules.CheckRules("<propertyy>");

etc.

That is, when an amount changes, it'll automatically check its rule, but you should also have it check the other properties as well.

That's one approach that could be applied to your problem.

 

gajit replied on Friday, October 20, 2006

Tried this approach and it still doesn't appear to work...
The business object remains as per my original post, but now in my property SETs for each property, I have;

Public Property ACCOUNTS() As Integer
        Get
            CanReadProperty(True)
            Return mACCOUNTS
        End Get
        Set(ByVal Value As Integer)
            CanWriteProperty(True)
            If mACCOUNTS <> Value Then
                mACCOUNTS = Value
                PropertyHasChanged()
                ValidationRules.CheckRules("ACCOUNTS")
                ValidationRules.CheckRules("UNITS")
                ValidationRules.CheckRules("UNITVALUE")
                ValidationRules.CheckRules("ORDERVALUE")

            End If
        End Set

Am I still missing something?

Thanks,
gaj.




Brian Criswell replied on Friday, October 20, 2006

The CheckRules calls have to go before PropertyHasChanged().  PropertyHasChanged() fires the PropertyChanged event for the property which signals to data binding and the ErrorProvider to do their stuff.  If the valid state changes after that, it will not be picked up.  Also, if you are going to use the reflection version of PropertyHasChanged, you need to mark your property with the NoInlining attribute.

gajit replied on Friday, October 20, 2006

That did it Brian, thank you!

hmmm. "reflection"..  i hate that word...  
Can i ask what Noinlining does?

Thanks,
Gaj



skagen00 replied on Friday, October 20, 2006

Inlining is a compiler trick to aid in performance - it would bring the code from CheckRules directly into your setter and run it in the context of your setter.

I'm curious myself to some degree - since the property names are being passed to checkrules, is this in fact needed? (Brian must know the answer to this one since he mentioned it!)

Brian Criswell replied on Friday, October 20, 2006

PropertyHasChanged() (with an empty parameter list) uses reflection to determine which property changed.  If you build in release mode and the property gets inlined, it no longer is in that property and PropertyHasChanged would not pick it up properly.

gajit replied on Friday, October 20, 2006

Brian Criswell:
PropertyHasChanged() (with an empty parameter list) uses reflection to determine which property changed.  If you build in release mode and the property gets inlined, it no longer is in that property and PropertyHasChanged would not pick it up properly.


So how is the NoInline implemented? As part of the Property definition? A keyword help search has proven fruitless...

Thanks,
gaj.

Reflection - no specific questions Brian - but thanks for offering. it has been a little while since I read the CSLA book, but although not totally confused, didn;t quite 'get it' .. and moved ahead taking a 'leap of faith' that it would work. I have yet to implement my csla project across tiers as of yet (other than client-database server) so not sure how much knowledge I will need ...





Brian Criswell replied on Friday, October 20, 2006

gajit:

hmmm. "reflection"..  i hate that word...

Do you have any specific concerns about reflection?

xal replied on Friday, October 20, 2006

You can avoind making all those calls in the property sets by adding dependant properties.
This is a new 2.1 feature. Basically, when you are adding business rules, you also call:
ValidationRules.AddDependantProperty("propertyA","propertyB")

Andrés

gajit replied on Friday, October 20, 2006

Thanks Andres, but I'm stuck on 2.0 at the moment, and don't have the resources right now to make the move... (plus I'm a little scared..:).. )

There are also other features of 2.1 - such as the varying degrees of rules validation that i would like to take advantage of...

gaj.









Copyright (c) Marimer LLC