WPF - Error when using ValidationStep

Topics: Validation Application Block
Jul 19, 2011 at 1:55 PM

We need to update the source when a validation on a control fails.   So we tried using ValidationStep to achieve that.  
The source gets updated but we get the following error from the control being validated.

"Value to validate is not the expected type:  expected System.String but got System.Windows.Data.BindingExpression instead."
We are using EntLib 5.


<TextBox Width="80" Validation.ErrorTemplate="{StaticResource ValidationErrorTemplate}">
                                <Binding Path="User.NAS" UpdateSourceTrigger="LostFocus">
                                        <vab:ValidatorRule ValidationStep="UpdatedValue" SourceType="{x:Type ent:User}" SourcePropertyName="NAS" />

Custom control
  public override void DoValidate(object objectToValidate, object currentTarget, string key, ValidationResults validationResults)
            string nas = (string)objectToValidate;
            Regex nasRegex = new Regex(@"^\d{3}\s?\d{3}\s?\d{3}$");
            if (!nasRegex.IsMatch(nas))
                string message = string.Format(MessageTemplate, objectToValidate); 
                LogValidationResult(validationResults, message, currentTarget, key);
Validation template
  <ControlTemplate x:Key="ValidationErrorTemplate">
        <StackPanel Orientation="Horizontal">
            <AdornedElementPlaceholder />
            <Image Height="16" Width="16" ToolTip="{Binding [0].ErrorContent}" Source="/J499A1_01A_RA_RessourcesApp_PC;component/Images/stop.ico" />
Jul 20, 2011 at 1:40 PM


I'm not really familiar with ValidationStep but the WPF Integration Documentation is pointing to this link on how to configure the validation on binding processing pipeline. I hope this somehow helps.


Noel Angelo Bolasoc
Global Technologies and Solutions
Avanade, Inc.
Contact Us

Jul 22, 2011 at 2:56 PM
Edited Jul 22, 2011 at 5:25 PM

Hi AvanadeSupport.  That link is really not  very helpful.  We're having the same problem with:


The specific scenario we are trying to accomplish is to allow for the value being validated (typed in by the user) to pass through to a view-model in an M-V-VM scenario so that the view-model (as source in this binding) is synchronized with the data in the view (the WPF control).  The default behavior causes broken validation rules to prevent updating of the source (the requirement of the original post as well as our own).  When we change the default behavior to CommittedValue (or UpdatedValue) the source gets updated, but the validation rule throws the error which winds up attached to the errors for the control, accessed via:



Can someone who is familiar with the Validation Block and the varying behaviors of ValidationStep please shed some more light on why the ValidationRule (specifically Microsoft.Practices.EnterpriseLibrary.Validation.Validators.ValueAccessValidator.DoValidate() line 65)  would erroneously attempt to validate a BindingExpression as opposed to the actual text in either of these cases and how we can work around (or preferably correct) this?

David Anthony

Baker Hughes

Jul 22, 2011 at 8:35 PM

We are experiencing similar problems with VAB integration with WPF, also using the MVVM pattern (actually a hybrid MVP+VM pattern, but close enough in this case). 

We need our UI fields to validate when they lose focus, but we also need full form validation if the user clicks the "Ok" button, at which point any validation errors will be displayed in a MessageBox.

The most natural way to achieve this is to apply the validation rules to the controls in XAML markup (UpdateSourceTrigger="LostFocus"), and then attempt to validate the full source object on OK click.  But this will only work if the invalid values are applied to our source object.  We thought the ValidationStep property would solve this (UpdatedValue or CommittedValue), but alas, it does not seem to be work.  This is such a shame.  If this worked as expected, we would have a really clean architecture with validation possible at the View and Presenter levels.

Since this doesn't seem to be the case, has anyone found a clean workaround? 

I tried handling the LostFocus event on the controls, and forcing an update of the source:


But that doesn't work either. The VAB is awesome otherwise, and I'm really reluctant to abandon it because of this (seemingly) small issue...

Jul 25, 2011 at 3:42 PM
Edited Jul 25, 2011 at 7:03 PM

I looked up the ValidatorRule class that existed. It explicitely said in the comments that only ConvertedProposedValue is supported, because it receives a binding expression otherwise.

I heavily modified the class to be able to handle binding expressions using reflection. However, it does not supports path that contains index brackets '[0]'. Hope that helps.

using System;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Windows.Controls;
using System.Windows.Data;
using Microsoft.Practices.EnterpriseLibrary.Validation;
using SWC = System.Windows.Controls;
namespace namespaceTest
    public class CommitedValueValidatorRule : ValidationRule
        public string RulesetName { getset; }
        public CommitedValueValidatorRule() : base(ValidationStep.CommittedValue, false) {}
        public override SWC.ValidationResult Validate(object value, CultureInfo cultureInfo)
            BindingExpression binding = (BindingExpression)value;
            string fullPath = binding.ParentBinding.Path.Path;
            Type type = null;
            PropertyInfo propertyInfo = null;
            object propertyValue = binding.DataItem;
            string[] properties = fullPath.Split('.');
            foreach (string propertyName in properties)
                type = propertyValue.GetType();
                propertyInfo = type.GetProperty(propertyName);
                propertyValue = propertyInfo.GetValue(propertyValue, null);
            Validator validator = PropertyValidationFactory.GetPropertyValidator(
                RulesetName ?? string.Empty,
                new FixedPropertyMemberValueAccessBuilder(propertyInfo)
            ValidationResults validationResults = validator.Validate(propertyValue);
            return new SWC.ValidationResult(validationResults.IsValid, validationResults.IsValid ? null : validationResults.First().Message);
        private class FixedPropertyMemberValueAccessBuilder : MemberValueAccessBuilder
            private readonly PropertyInfo property;
            public FixedPropertyMemberValueAccessBuilder(PropertyInfo property)
                this.property = property;
            protected override ValueAccess DoGetFieldValueAccess(FieldInfo fieldInfo)
                throw new NotSupportedException();
            protected override ValueAccess DoGetMethodValueAccess(MethodInfo methodInfo)
                throw new NotSupportedException();
            protected override ValueAccess DoGetPropertyValueAccess(PropertyInfo propertyInfo)
                if (this.property == propertyInfo)
                    return new ExternalValueValueAccess();
                throw new NotSupportedException();
        private class ExternalValueValueAccess : ValueAccess
            public ExternalValueValueAccess()
            { }
            public override bool GetValue(object source, out object value, out string valueAccessFailureMessage)
                var companion = new ExternalValue() { PropertyValue = source };
                if (companion != null)
                    value = companion.PropertyValue;
                    valueAccessFailureMessage = null;
                    return true;
                throw new ArgumentException("ExceptionUnexpectedValueSource""source");
            public override string Key
                get { return ""; }
        private class ExternalValue
            public object PropertyValue { getset; }

Jul 25, 2011 at 6:54 PM

risc024:  Thanks for the reply!  This looks like a decent solution to the problem.  I guess I wanted to avoid writing my own replacement for the VAB ValidatorRule, but hey, if that's what it takes. 

Cheers.  :)

Jul 27, 2011 at 4:47 AM

I published this as an issue for EntLib, go upvote it if you agree. That way It'll be supported in the next version so no more hand-crafted class.