How to implement data validation in wpf by clicking submit button in a mvvm pattern

Kalpana 291 Reputation points
2022-03-11T08:55:02.43+00:00

Hi

I would like to get some thoughts on how to get the button in the wpf to show message when the textbox is empty . How do I go about doing it, theoretical advice would be good, I plan to code myself. I just am getting confused with should I use INotifyDataErrorInfo or INotifyPropertyChanged in this case.

Developer technologies C#
{count} votes

Accepted answer
  1. Karen Payne MVP 35,586 Reputation points Volunteer Moderator
    2022-03-11T12:01:04.347+00:00

    Consider using data annotations.

    For a simple example, validate user name and password (along with password confirmation)

    using System.ComponentModel.DataAnnotations;  
    using ValidateLoginCore.Classes.ValidationRules;  
      
    namespace ValidateLoginCore.Classes  
    {  
        public class CustomerLogin  
        {  
            /// <summary>  
            /// User name  
            /// </summary>  
            /// <returns>User name for login</returns>  
            [Required(ErrorMessage = "{0} is required"), DataType(DataType.Text)]  
            [StringLength(10, MinimumLength = 6)]  
            public string UserName { get; set; }  
            /// <summary>  
            /// User password which must match PasswordConfirmation using  
            /// PasswordCheck attribute  
            /// </summary>  
            /// <returns>plain text password</returns>  
            [Required(ErrorMessage = "{0} is required"), DataType(DataType.Text)]  
            [StringLength(20, MinimumLength = 6)]  
            [PasswordCheck(ErrorMessage = "Must include a number and symbol in {0}")]  
            public string Password { get; set; }  
            /// <summary>  
            /// Confirmation of user password  
            /// </summary>  
            /// <returns>plain text password</returns>  
            [Compare(  
                 "Password",   
                 ErrorMessage = "Passwords do not match, please try again"),   
             DataType(DataType.Text)]  
            [StringLength(20, MinimumLength = 6)]  
            public string PasswordConfirmation { get; set; }  
            public override string ToString() => UserName;  
      
        }  
    }  
    

    Custom attribute

    using System.ComponentModel.DataAnnotations;  
    using System.Text.RegularExpressions;  
      
    namespace ValidateLoginCore.Classes.ValidationRules  
    {  
        public class PasswordCheck : ValidationAttribute  
        {  
            public override bool IsValid(object value)  
            {  
                var validPassword = false;  
                var reason = string.Empty;  
                var password = (value == null) ? string.Empty : value.ToString();  
      
                if (string.IsNullOrWhiteSpace(password) || password.Length < 6)  
                {  
                    reason = "new password must be at least 6 characters long. ";  
                }  
                else  
                {  
                    var pattern = new Regex("((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%]).{6,20})");  
                    if (!pattern.IsMatch(password))  
                    {  
                        reason += "Your new password must contain at least 1 symbol character and number.";  
                    }  
                    else  
                    {  
                        validPassword = true;  
                    }  
                }  
      
                if (validPassword)  
                {  
                    return true;  
                }  
                else  
                {  
                    return false;  
                }  
      
            }  
      
        }  
    }  
    

    Here when there is an issue we present a message box. For bonus points we could have this information show up in labels which for WPF requires a tad bit more code.

    182206-figure1a.png

    Say we want to validate an SSN passed the usual validation on length

    using System;  
    using System.ComponentModel.DataAnnotations;  
    using System.Text.RegularExpressions;  
      
    namespace ValidationCoreLibrary.CommonRules  
    {  
        /// <summary>  
        /// Is a valid SSN  
        /// </summary>  
        /// <returns>True if valid, false if invalid SSN</returns>  
        /// <remarks>  
        ///  
        /// Handle some commonly encountered “fake” values or ones that might easily be forged in  
        /// an area that might require a user to enter one.  
        ///   
        /// ^                                       #Start of expression  
        /// (?!\b(\d)\1+-(\d)\1+-(\d)\1+\b)         #Don't allow all matching digits for every field  
        /// (?!123-45-6789|219-09-9999|078-05-1120) #Don't allow "123-45-6789", "219-09-9999" or "078-05-1120"  
        /// (?!666|000|9\d{2})\d{3}                 #Don't allow the SSN to begin with 666, 000 or anything between 900-999  
        /// -                                       #A dash (separating Area and Group numbers)  
        /// (?!00)\d{2}                             #Don't allow the Group Number to be "00"  
        /// -                                       #Another dash (separating Group and Serial numbers)  
        /// (?!0{4})\d{4}                           #Don't allow last four digits to be "0000"  
        /// $                                       #End of expression  
        /// </remarks>  
        [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]  
        public class SocialSecurityAttribute : ValidationAttribute  
        {  
            //public string SocialValue { get; set; }  
      
            public override bool IsValid(object value) =>  
                value is string && Regex.IsMatch(value.ToString().Replace("-", ""),  
                    @"^(?!\b(\d)\1+\b)(?!123456789|219099999|078051120)(?!666|000|9\d{2})\d{3}(?!00)\d{2}(?!0{4})\d{4}$");  
        }  
    }  
    

    In a class usage

    public class Person  
    {  
        /// <summary>  
        /// First name  
        /// </summary>  
        [Required(ErrorMessage = "{0} is required"), DataType(DataType.Text)]  
        [StringLength(20, MinimumLength = 6)]  
        public string FirstName { get; set; }  
          
        /// <summary>  
        /// Last name  
        /// </summary>  
        [Required(ErrorMessage = "{0} is required"), DataType(DataType.Text)]  
        [StringLength(10)]  
        public string LastName { get; set; }  
          
        /// <summary>  
        /// Phone number  
        /// </summary>  
        [Required(ErrorMessage = "{0} is required"), DataType(DataType.Text)]  
        [Phone]  
        public string Phone { get; set; }  
          
        /// <summary>  
        /// Social Security number  
        /// </summary>  
        [SocialSecurity] public string SSN { get; set; }  
      
        public override string ToString() => $"{FirstName} {LastName} {SSN}";  
      
    }  
    
    0 comments No comments

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.