title: Can we use touched and dirty event in WPF for validation?
body: <p>Data Annotation helped us to validate all the fields in a form filled by the user but not able to validate fields which are untouched by the user. What would be the method to validate untouched fields. Is there any substitute for dirty event that is used in angular for WPF. We are using WPF with MVVM in our project.</p>
  <p><strong>MODEL</strong></p>
  <pre><code> public class mCategory 
      {
          [Key]
          public Int32 CatID { get; set; }
  
          [Required]
          [MaxLength(15)]
          [RegularExpression(&quot;^(?=.*[a-zA-Z])(?=.*[0-9])[A-Za-z0-9]+$&quot;)]
          public string Alias { get; set; }
  
          [Required]
          [MaxLength(8)]
          [RegularExpression(&quot;^(?=.*[a-zA-Z])(?=.*[0-9])[A-Za-z0-9]+$&quot;)]
          public String Tag { get; set; }
  
          [Required]
          [MaxLength(50)]
          [RegularExpression(&quot;^[a-zA-Z]*$&quot;)]
          public string Name { get; set; }
      }
  </code></pre>
  <p><strong>VIEW MODEL</strong></p>
  <pre><code>public class vmOfficeCategory: INotifyPropertyChanged, INotifyDataErrorInfo
      {
          #region Declaration
          private mOfficeCategory _officecategory;
  
          private ObservableCollection&lt;mOrganization&gt; _lstOrganization;
          private ObservableCollection&lt;mDepartment&gt; _lstDepartment;
  
          private ObservableCollection&lt;mOfficeCategory&gt; _lstOfficeCategory;
  
          #endregion
          #region ViewModel Properties
  
  
          public string Parent
          {
              get
              {
                  return _officecategory.Parent;
              }
              set
              {
                  _officecategory.Parent = value;
                  Validate(value);
                  RaisePropertyChanged(&quot;Parent&quot;);
              }
          }
  
          public string Code
          {
              get { return _officecategory.Code; }
              set
              {
                  _officecategory.Code = value;
                  Validate(value);
                  RaisePropertyChanged(&quot;Code&quot;);
              }
          }
  
  
          public string Alias
          {
  
              get { return _officecategory.Alias; }
              set
              {
                  _officecategory.Alias = value;
                  Validate(value);
                  RaisePropertyChanged(&quot;Alias&quot;);
              }
          }
  
          public string Tag
          {
              get
              {
                  return _officecategory.Tag;
              }
              set
              {
                  _officecategory.Tag = value;
                  Validate(value);
                  RaisePropertyChanged(&quot;Tag&quot;);
  
              }
          }
          public string Name
          {
              get
              {
                  return _officecategory.Name;
              }
              set
              {
                  _officecategory.Name = value;
                  Validate(value);
                  RaisePropertyChanged(&quot;Name&quot;);
              }
          }
          public ObservableCollection&lt;mOfficeCategory&gt; lstOfficeCategory
          {
              get
              {
                  return _lstOfficeCategory;
              }
              set
              {
                  _lstOfficeCategory = value;
                  RaisePropertyChanged(&quot;lstOfficeCategory&quot;);
              }
          }
          #endregion
  
          public vmOfficeCategory()
          {
            _officecategory = new mOfficeCategory();
              RegisterCommands();
          }
  
          #region Command
          public ICommand SubmitCommand { get; set; }
          public ICommand ResetCommand { get; set; }
          #endregion
          /// &lt;summary&gt;
          /// Initialize Command.
          /// 
          /// &lt;/summary&gt;
          /// 
  
          private void RegisterCommands()
          {
              SubmitCommand = new SyncRelayCommand(Add, x =&gt; true);
              ResetCommand = new SyncRelayCommand(Reset, x =&gt; true);
          }
          private void Add(object obj)
          {
              _lstOfficeCategory = new ObservableCollection&lt;mOfficeCategory&gt;();
              lstOfficeCategory.Add(_officecategory);
          }
          private void Reset(Object obj)
          {
              this.Code = string.Empty;
              this.Alias = string.Empty;
              this.Tag = string.Empty;
              this.Name = string.Empty;
          }
  
          #region PropertyChanged
          protected void RaisePropertyChanged(string propertyName)
          {
              var handler = PropertyChanged;
  
              if (handler != null)
              {
                  handler(this, new PropertyChangedEventArgs(propertyName));
              }
          }
  
          private IDictionary&lt;string, List&lt;string&gt;&gt; _errors = new Dictionary&lt;string, List&lt;string&gt;&gt;();
          private void Validate(object val, [CallerMemberName] string propertyName = null)
          {
              if (_errors.ContainsKey(propertyName)) _errors.Remove(propertyName);
  
              ValidationContext context = new ValidationContext(_officecategory) { MemberName = propertyName };
              List&lt;ValidationResult&gt; results = new List&lt;ValidationResult&gt;();
  
              if (!Validator.TryValidateProperty(val, context, results))
              {
                  _errors[propertyName] = results.Select(x =&gt; x.ErrorMessage).ToList();
              }
  
              ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
          }
  
          public bool HasErrors =&gt; _errors.Any();
  
          public event EventHandler&lt;DataErrorsChangedEventArgs&gt; ErrorsChanged;
  
          public IEnumerable GetErrors(string propertyName)
          {
              return _errors.ContainsKey(propertyName) ? _errors[propertyName] : null;
          }
  
          public event PropertyChangedEventHandler PropertyChanged;
          #endregion
      }
  </code></pre>