Question

I'm trying to configure my validations to only trigger when I click the save button. I've never used IDataErrorInfo before so from the start I'm not very clear on how to set this up. I am trying to stay MVVM path. Is there something I can call to manually have my fields validated on click of save button?

Implement:

 IDataErrorInfo

Textbox XAML:

     Text="{Binding Name, Mode=TwoWay, ValidatesOnDataErrors=True}" />         

Code:

    public string Error
    {
        get { throw new NotImplementedException(); }
    }

    public string this[string columnName]
    {
        get
        {
            if (columnName == "Name")
            {
                if (!Name.Length() >= 6)
                {
                    return "Name must be 6 chars.";
                }
                else
                {
                    return null;
                }
            }
            return null;
        }
    } 

Save Command:

    private void Save() {
       //db save, etc..
       Need to validate all properity fields

    }
Was it helpful?

Solution

I use IValidateableObject. If your object class implements this interface it exposes the validate method that you can override, then you can call this validation on the object.validate only when you want. It returns true or false. Within that validation function you can loop through your objects properties and add the columns you need to the IDataerrorInfo based on your custom bunisness logic. I do this by creating a Validationbase class that gets inherited by my model/object class.

Here is an example of my validation base class that you can inherit into your model/object class:

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.ComponentModel;
using System.Collections.Concurrent;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

public class ValidationBase : IValidatableObject, IDataErrorInfo, INotifyPropertyChanged
{

         #region "DECLARATIONS"
         protected Dictionary<string, string> _propertyErrors = new Dictionary<string, string>();
         protected List<ValidationResult> _validationResults = new List<ValidationResult>();
         public bool HasErrors {
                 get { return (_propertyErrors.Count + _validationResults.Count) > 0; }
         }
         #endregion
         #region "IValidatableObject IMPLEMENTATION"
         public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
         {
                 return null;
         }
         #endregion
         #region "iDataError OBJECTS"
         //Returns an error message
         //In this case it is a general message, which is
         //returned if the list contains elements of errors
         public string Error {
                 get {
                          if (_propertyErrors.Count > 0) {
                                   return "Object data is invalid";
                          } else {
                                   return null;
                          }
                 }
         }

         public string this[string columnName] {
                 get {
                          if (_propertyErrors.ContainsKey(columnName)) {
                                   return _propertyErrors[columnName].ToString();
                          } else {
                                   return null;
                          }
                 }
         }

         #endregion
         #region "IDataError FUNCTIONS"
         //Adds an error to the collection, if not already present
         //with the same key
         protected void AddError(string columnName, string msg)
         {
                 if (!_propertyErrors.ContainsKey(columnName)) {
                          _propertyErrors.Add(columnName, msg);
                          OnPropertyChanged(columnName);
                 }
         }

         //Removes an error from the collection, if present
         protected void RemoveError(string columnName)
         {
                 if (_propertyErrors.ContainsKey(columnName)) {
                          _propertyErrors.Remove(columnName);
                          OnPropertyChanged(columnName);
                 }
         }
         public void ClearErrors()
         {
                 _propertyErrors.Clear();
         }
         #endregion
         #region "INotifyPropertyChanged IMPLEMENTATION"
         public event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged;
         public delegate void PropertyChangedEventHandler(object sender, PropertyChangedEventArgs e);

         protected virtual void OnPropertyChanged(string propertyName)
         {
                 if (PropertyChanged != null) {
                          PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                 }
         }
         #endregion

}

if you are using entity framework as your model i believe the validate method will be called before the object is saved via db.SaveChanges

here is how you can implement the validationbase in your model:

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
public partial class vendor : ValidationBase
{

    #region "PROPERTIES"
    public bool HasChanges { get; set; }
    #endregion

    #region "VALIDATION FUNCTIONS"

    public override IEnumerable<ComponentModel.DataAnnotations.ValidationResult> Validate(ComponentModel.DataAnnotations.ValidationContext validationContext)
    {
        return base.Validate(validationContext);
        PropertyValitaion(true);
    }

    public void PropertyValitaion(bool bAllProperties, string sProperty = "")
    {
        //your property specific logic goes here


    }
    #endregion

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top