microsoft / xaml-standard

XAML Standard : a set of principles that drive XAML dialect alignment
Other
807 stars 54 forks source link

Add ValidationRules for all controls #196

Open taori opened 7 years ago

taori commented 7 years ago

Please have a look at post number 2 on #18.

I think it would be exceptionally useful if it was a baseline feature to have validationrules work for xaml.

However unlike they do currently, they should be dependecyobjects instead of freezables in order support depecendy property based validation to allow for a more flexible validation.

In the past of me using WPF the biggest pit fall of using ValidationRules was their lack of dependency properties, and me having to bypass those issues by writing plenty workaround code.

birbilis commented 7 years ago

Do UWP/Xamarin.Forms have Freezables at all? WPF had, but Silverlight didn't from what I remember

taori commented 7 years ago

@birbilis As far as i can recall Xamarin.Forms does not provide an equivalent feature. Regarding UWP i have no idea because i did not try it out yet.

However no matter the platform this is a feature which is used all over the place - Working with this concept is far more convenient than the verbose viewmodel based way of providing properties for each and every field rather than "attaching" validation rules, which ideally provide DependencyProperty dependant functionality

JerryNixon commented 7 years ago

tl;dr; I believe that your recommendation is far from sufficient for real validation.

Generally speaking, a field is not validated by the content of just that field. For example, my down payment amount is validated by a combination of the loan amount, the loan type, and the property value. I could plausibly come up with a complex binding to inject this combination of values and manipulate them into the threshold through an IValueConverter but this puts all my logic in the wrong place.

I want your recommended type of simple validation, yes; it has its place. But, I want to be able to validate my data in my view-model, giving me the option to put my logic there, or even calling out to a rules engine or business tier. What you have suggested is fine for simple things, but there is so much more to make validation work.

Allow me to review the legacy of XAML validation approaches:

In Silverlight we used BindingValidationError where the view-model would throw an exception in a property's setter and you would handle BindingValidationError (an event) on the container, then show the error(s) in a custom interface of some kind. It moved the logic to the view-model, but required exceptions and limited us to the synchronous world of property setters. This did not cut it.

In WPF we had ExceptionValidationRules and is basically what you are suggesting above - with the exception that the rule was actually a custom class. It was implemented as a property of the Binding class. This allowed your logic to be in a different, reusable context. Even though this was nice, the resulting clutter in your namespaces and XAML was astronomical by the time you build a large form.

ASP.NET still uses DataAnnotations which do what you are suggesting as attributes within the DTO. This is a cute approach but is a far cry from the complexity required to meet the needs of enterprises. It also means you have to update your DTO classes with your business logic and change your DTO when your business logic changes. It's nice for required, perhaps, but generally short sited, IMHO.

Side-stepping the weight of BindingValidationError (above) WPF gave us the option to use IDataErrorInfo which required our view-model to inherit from and implement the interface's two properties Error and Item[string] which gives the error of the object and the error message for the property with a given name. This really upgraded our options to a good place.

But Silverlight enhanced IDataErrorInfo to INotifyDataErrorInfo which works more like INotifyPropertyChanged in our view-models. It's ErrorsChanged event allowed for validating data to be asynchronous and THEN bubbling up the trouble after interrogation. The interface also included a HasErrors property and a GetError() method. Implementation was simple, and it addressed everything that was wrong with the previous approaches.

This also required the developer to handle BindingValidationError on the container (just like before) and used the additional binding properties of NotifyOnValidationError and ValidatesOnDataErrors within the XAML declaration. There was a learning curve, but implementation was a sophisticated, comprehensive solution.

Please consider

So, I would recommend we add to this issue the pieces and parts that make INotifyDataErrorInfo work in the XAML Standard. Validation is an important part of apps in enterprise development and it is a gaping hole in UWP-XAML today. Implementing a half-baked validation framework just means developers will not use it because, basically they cannot use and meet the requirements of their business.

https://msdn.microsoft.com/en-us/library/system.componentmodel.inotifydataerrorinfo(v=vs.95).aspx

A little more

Having said all that, I also believe that other features, not specific to XAML, but specific to handling validation should also be part of the namespace, even if you require developers to implement them on their own - like we do for INotifyPropertyChanged and ICommand today. Those include:

  1. The ability to iterate properties without reflection
  2. The ability to iterate properties and ask if they are valid
  3. The ability to iterate properties and ask if they are dirty
  4. The ability to iterate properties and revert them (basically setting their current value to their original value resulting in their dirty property to return false).
  5. The ability to iterate through properties and mark them as clean (basically setting their original value to their current value resulting in their dirty property to return false).
  6. The ability to do the above on a class-level (mark all as clean, revert all, etc.)

Perhaps we call it IValidationAware and when we define it we remember that many validation frameworks require an asynchronous call-out to comprehensively validate models.

In conclusion

The reality is, line-of-business developers building apps for enterprises have to do this anyway. They have no choice but to build their own and code their own and test their own. Every solution is similar and every solution is different. It makes sense for the XAML standard to solve scenarios common to most developers and to do so in a comprehensive way already proven in an earlier specification.

Thanks for reading.

taori commented 7 years ago

@JerryNixon Nice input. I kind of agree that the way WPF solved it was lacking (for me most things would have been solvable easy enough, if dependency properties on validationrules would have been possible at all).

While in one aspect having at least some similar validation concept would be nice, i am certain most people would accept a fresh, more flexible approach at validation too, even if it meant breaking changes.

In some aspect i disagree with you. While validation and value history/management are used in combination, i don't think they should be strictly enforced together. Obviously depending on how one would implement such a framework i would be open for trying it.

If this were a "you get nothing or you get what wpf currently supports"-situation i would still prefer "what wpf currently supports" though. While there are certainly more difficult validation scenarios which was awful to manage with validation rules so far, it is still nice to have the ability to validate numbers, regex, phone numbers, etc.

GeraudFabien commented 7 years ago

I also would like to have asp.net MVC like on dataBinding. What i mean is you made your anotation on the model. You tel your control wich property it display. If it's an editable label it validate the value base on anotation. But this have nothinks to do with Xaml standart. it's just my pov of how i would like to do. But it require specific control...