Print Page | Close Window

Validate on button click?

Printed From: IdeaBlade
Category: DevForce
Forum Name: DevForce 2010
Forum Discription: For .NET 4.0
URL: http://www.ideablade.com/forum/forum_posts.asp?TID=2006
Printed Date: 10-Jun-2026 at 5:28pm


Topic: Validate on button click?
Posted By: mikewishart
Subject: Validate on button click?
Date Posted: 26-Jul-2010 at 11:57am
I was wondering if there's an easy way to validate an entity on a button click rather than setting up the verification engine to update as every property is changed (ala: Manager.VerifierEngine.DefaultVerifierOptions.ErrorNotificationMode = VerifierErrorNotificationMode.ThrowException).

If I have XAML like this:
<TextBox  Text="{Binding Employee.FirstName, Mode=Default, ValidatesOnExceptions=True}"/>

<Button Content="Validate" Command="{Binding BtnValidateClick}"/>

and in my viewmodel, I have a property and method:
public static Employee Employee { get; set; }

public ICommand BtnValidateClick { get; set; }  // this gets set to OnBtnValidateClick in the vm constructor
public void OnBtnValidateClick(object parameter)
{
  var result = Manager.VerifierEngine.Execute(Employee).Where(r => r.IsError || r.IsWarning);
}


What can I do with the result to tell the entity to go throw errors on all the properties with failed verifiers?   I'm thinking there's something simple I'm missing here.

Thanks!



Replies:
Posted By: GregD
Date Posted: 27-Jul-2010 at 10:53am
Are you working in WPF or Silverlight?


Posted By: mikewishart
Date Posted: 27-Jul-2010 at 10:54am
This is for WPF


Posted By: GregD
Date Posted: 27-Jul-2010 at 5:34pm
The WPF UI machinery predates the INotifyDataErrorInfo interface (which is implemented by DevForce entities), so the WPF UI doesn't listen for the ErrorsChanged event that an entity raises when an error is added to its ValidationErrors collection. You'll need to wire up a handler yourself.


Posted By: mikewishart
Date Posted: 29-Jul-2010 at 7:37am
Thanks Greg.  I came up with two ways to do it in an injected base class.

In the interest of helping any other developers with the same question, here's one way.  (It's not fun finding forum posts with "I figured it out," but no answer as to how.)  This way clears the error until Verify() is called again.  Bindings need to include ValidatesOnDataErrors=true.

public abstract partial class EntityBase : IDataErrorInfo
{
  private Dictionary<string, string> _errorList;
  private Dictionary<string, string> ErrorList
  {
    get { return _errorList ?? (_errorList = new Dictionary<string, string>()); }
  }
  private bool _isVerifying;

  /// <summary>
  /// Verify the specific entity, setting errors on properties not passing validation.
  /// </summary>
  /// <returns>
  /// True if the entity passes validation.  False if there are errors.
  /// </returns>
  public bool Verify()
  {
    ErrorList.Clear();

    var verifiers = verifierEngine.Execute(this)
      .Where(v => (v.ResultCode == VerifierResultCode.Error) || (v.ResultCode == VerifierResultCode.OkWarning))
      .ToList();

    _isVerifying = true;
    try
    {
      foreach (var verifierResult in verifiers)
      {
        var triggers = verifierResult.Verifier.TriggerLinks;
        foreach (var propertyName in triggers.Select(trigger => trigger.TriggerItem.MemberName))
        {
          if (ErrorList.ContainsKey(propertyName))
            ErrorList[propertyName] += Environment.NewLine + verifierResult.Message;
          else
            ErrorList.Add(propertyName, verifierResult.Message);

          if (GetType().GetProperty(propertyName) != null)
            EntityAspect.ForcePropertyChanged(new PropertyChangedEventArgs(propertyName));
        }
      }
    }
    finally
    {
      _isVerifying = false;
    }

    return verifiers.Count == 0;
  }

  /// <summary>
  /// Hide the error whenever the property is changed until Verify() is called again.
  /// </summary>
  protected override void OnPropertyChanged(PropertyChangedEventArgs e)
  {
    base.OnPropertyChanged(e);
    if (_isVerifying) return;

    if (string.IsNullOrEmpty(e.PropertyName)) return;

    if (ErrorList.ContainsKey(e.PropertyName))
      ErrorList.Remove(e.PropertyName);
  }

  public new string this[string propertyName]
  {
    get { return ErrorList.ContainsKey(propertyName) ? ErrorList[propertyName] : null; }
  }

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


Posted By: GregD
Date Posted: 02-Aug-2010 at 11:36am
Thanks very much for posting your solution, Mike!


Posted By: BringerOD
Date Posted: 28-Aug-2010 at 11:05am
Mike,
 
Thanks for the post.  Is there a way to run the validation when the user leaves the field.  Not just on the button click.
 
I tried it using an interceptor and it worked.  I was hoping a global solution would be around. Maybe an interceptor that works on all fields and tried to verify after each set.
 
Bryan


Posted By: mikewishart
Date Posted: 31-Aug-2010 at 1:11pm
If you set the default verifier option mode, this should happen.

Manager.VerifierEngine.DefaultVerifierOptions.ErrorNotificationMode = VerifierErrorNotificationMode.ThrowException

of course, you'll need to use ValidatesOnExceptions=true in your xaml.


Posted By: BringerOD
Date Posted: 31-Aug-2010 at 1:20pm
Mike,
 
Thanks that is the way to go for WPF currently.
 
Bryan



Print Page | Close Window