HELP ! - with MVVM and binding ....

This forum is meant for anything you would like to share with other visitors
Post Reply
User avatar
Phil Hepburn
Posts: 743
Joined: Sun Sep 11, 2016 2:16 pm

HELP ! - with MVVM and binding ....

Post by Phil Hepburn »

Hi guys,

I guess I am probably talking with Nick (Friend) in asking you all for some help and guidance.

As you may be aware, I have been doing a lot recently with coding in X# WPF forms to handle data validation. And as such I have been creating Validation Rule classes and applying them to XAML script in my mark-up section.

Here is how we switch-on the VR to be used :-
Masking_02.jpg
Masking_02.jpg (62.34 KiB) Viewed 277 times
This works - BUT - as you will have noticed Nick does not play to the rules of the MVVM pattern of approach. We are using a names pace in the XAML script header - see below :-
Validation_11.jpg
Validation_11.jpg (102.89 KiB) Viewed 277 times
to access directly a .NET class in my code files with namespace 'MyClasses'. Two more small images show this below :-
Validation_12.jpg
Validation_12.jpg (69.06 KiB) Viewed 277 times
Validation_13.jpg
Validation_13.jpg (84.42 KiB) Viewed 277 times
Now then Nick / guys, what I need to know is that if I use the MVVM light framework, can I bind the class to the TextBox and have it behind in the ViewModel in some way ?

I know you use the DevExpress controls and this may do stuff for you, BUT, are you at least aware of this way I can clean things up MVVM wise ?

TIA,
Phil.
Wales, UK.
NickFriend
Posts: 248
Joined: Fri Oct 14, 2016 7:09 am

HELP ! - with MVVM and binding ....

Post by NickFriend »

Hi Phil,

I'm not sure I can be of much use to you with this. I use IDataErrorInfo for validation, in which case it's all handled at the ViewModel or individual data object level.

Masking is a separate issue - since that's basically visual it makes sense to handle it in the view (in the xaml).

If you Google "ValidationRule vs IDataErrorInfo" you get several useful articles discussing the pros and cons.

Nick
Mark

HELP ! - with MVVM and binding ....

Post by Mark »

Hi Phil,

We use INotifyDataErrorInfo, it's an enhanced replacement for IDataErrorInfo and much more useable than the much earlier ValidationRule.

In one system, I use a class that I have extended from the article in MVVM viewmodel
I needed to be able to set validations errors on a target UIElement other that the UIElement that initiated the error. e.g. when a combobox choice dictates that another field should be mandatory. Using this methodology, the validation rules for Bound Properties can be stated Declaratively is the static constructor of the view model; Note that the rules hold the Property Names as strings in a static RuleCollection<T> Rules.

So you end up with the following not very clearly understood code

Code: Select all

public class Truck1ViewModel : NotifyDataErrorInfo<Truck1ViewModel>
   {
       /// <summary>
       /// Initializes static members of the <see cref="Truck1ViewModel"/> class. 
       /// static constructor
       /// </summary>
       static Truck1ViewModel()
       {
            Rules.Add(new DelegateRule<Truck1ViewModel>(
            "Truck",
            "Value ?? Truck No.",
            x => x.Truck < 1));
            Rules.Add(new DelegateRule<Truck1ViewModel>(
            "Regono",
            "Value ?? Rego No.",
            x => string.IsNullOrEmpty(x.Regono) || x.Regono.Trim().Length == 0));
            Rules.Add(new DelegateRule<Truck1ViewModel>(
            "Odomtr",
            "Value ?? odoMeter",
            x => x.Odomtr < 1));
            Rules.Add(new DelegateRule<Truck1ViewModel>(
            "Fueltyp",
            "Values in [D],[U],[L]",
            x => string.IsNullOrEmpty(StaticEntityHelper.ValidateDomainValue(x.Fueltyp, "Fuel Type", "D", "U", "L")) == true));
            Rules.Add(new DelegateRule<Truck1ViewModel>(
            "Clientno",
            "Value ?? Client No.",
            x => string.IsNullOrEmpty(x.Clientno) || x.Clientno.Trim().Length == 0));
            Rules.Add(new DelegateRule<Truck1ViewModel>(
            "Release",
            "Values in [Y],[N]",
            x => string.IsNullOrEmpty(StaticEntityHelper.ValidateDomainValue(x.Release, "Released", "Y", "N")) == true));
   }
.......
}
I now tend to just use the .AddError and .RemoveError directy in the property setter; because the intention is much clearer.

e.g.

Code: Select all

/// <summary>
        /// Gets or sets the edited surname.
        /// </summary>
        public string Surname
        {
            get
            {
                return this.surnme;
            }

            set
            {

                this.surname = value;

                if (string.IsNullOrEmpty(value))
                {
                    this.AddError("Surname", "Surname may not be blank");
                }
                else
                {
                    this.RemoveError("Surnname");
                }
 
                this.OnPropertyChanged("Surname");
            }
        }



Which allows multiple property error validation and validationerrors setting. It's takes a bit of getting used to and you will have to make property wrappers for nested properties like EditedCustomer.Surname has to become EditedCustomerSurname because the rules collection is based on the property name.

e.g.

Code: Select all

/// <summary>
        /// Gets or sets the edited customer family name.
        /// </summary>
        public string EditedCustomerSurname 
        {
            get
            {
                return this.EditedCustomer?.Surname;
            }

            set
            {
                if (this.EditedCustomer== null)
                {
                    return;
                }

                this.EditedCustomer.Surname = value;

                [color=blue]this.ValidateSurname[/color](value);

                this.OnPropertyChanged("EditedCustomerSurname");
            }
        }
Post Reply