Delaying Validation in bound XAML fields until after initial user interaction?

Delaying Validation in bound XAML fields until after initial user interaction?

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


djcohen66 posted on Thursday, August 05, 2010

I am looking for a decent solution to a model validation/display issue in an MVVM implementation of CSLA using Silverlight.

We have built a simple model with fields like so:

        private static PropertyInfo<string> UsernameProperty = RegisterProperty<string>(c => c.Username);

        [Display(Description = "Username")]

        [Required(ErrorMessage = "Username required")]

        public string Username

        {

            get { return GetProperty(UsernameProperty); }

            set { SetProperty(UsernameProperty, value); }

        }

and used the AddBusinessRules method to activate the validation.  This works fine and when I bind the field to a text control the validation fires like a charm.  Unfortunately it fires the moment the field is displayed on the screen.  I would prefer that validation not highlight the required fields until after the user has attempted to submit the for the first time.

I found that I could get something close to the behavior I wanted by setting BusinessRules.SuppressRuleChecking = false; after AddBusinessRules was called and then setting it to true again when the set method of the model property was called.  However my co-worker feels, and I must agree, that this seems too much like monkeying with the model to satisfy behavior required in the UI and violates appropriate separation of concerns.

 

So how can I achieve my goal, maintain the purity of the model, and not put code in the code behind of the view?

RockfordLhotka replied on Friday, August 06, 2010

All the UI technologies generally work this way - as part of their binding process, they check to see if each property is valid and update the display accordingly. I don't know of any way to turn that behavior off in any of the UI technologies.

You can use rule short-circuiting to get some level of solution. Basically, create a rule that short-circuits if the object isn't in a state where you want the rules to run. Then attach that rule to every property at priority -1 (so it runs before any normal rules).

This way a new object will be valid up until the point the user interacts with it. Of course this implies you can detect that the user has interacted with the object - and there's no built-in mechanism for that either - at least by default.

So then what you can do is override the default MarkNew() behavior so a new object isn't dirty by default. That way, your short-circuit rule can stop processing if the object is not dirty, and only allow rules to run if the object is dirty.

djcohen66 replied on Friday, August 06, 2010

It would be nice if it were possible to change the value AllowEmptyStrings parameter of the Required attribute at runtime.

RockfordLhotka replied on Saturday, August 07, 2010

In CSLA 4 rule instances are shared across all instances of a business type, so there's no way to make persistent state changes to a rule without affecting all current (and future) instances of the corresponding business type.

I suspect that's true of the DataAnnotations attributes as well. It is very likely that one instance of the attribute is created for the type and is reused - though I don't know that for sure. I hope that's the case though, from a resource consuption perspective.

What this means, is that the difference in behavior can't rely on the state of the rule, it has to rely on the state of the business object instance. That's true for CSLA 4 rule objects, or for custom ValidationAttribute objects. Either technique allows you to create your own custom rule implementation where your rule can adapt to the state of the business object at runtime.

Copyright (c) Marimer LLC