WPF pasa la propiedad ViewModel a Validación

I have to following call in xaml to the validationRules and I would like to pass as an argument a viewmodel (that is in datacontext) property. How could I achive that?

                    <Binding.ValidationRules>
                        <vm:RiskCodeValidation/>
                    </Binding.ValidationRules> 

preguntado el 11 de junio de 12 a las 19:06

I know I can actually atribute a constant value to a property of the RiskCodeValidation, but I don't have any ideian how to pass a viewmodel's Atributte - the viewmodel is the datacontext of the window. -

2 Respuestas

If you set ValidationRule.ValidationStep to ValidationStep.CommitedValue or ValidationStep.UpdatedValue, value parameter in Validate method will be of type BindingExpression and you can get DataContext with BindingExpression.DataItem property.

Unfortunately, it works only after the binding source is updated.


Aquí hay un ejemplo:

public class RiskCodeValidation : ValidationRule
{
    public RiskCodeValidation()
        : base(ValidationStep.CommittedValue, true)
    {
    }

    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        var expression = value as BindingExpression;
        if (expression != null)
        {
            var sourceItem = expression.DataItem;
            if (sourceItem != null)
            {
                var propertyName = expression.ParentBinding != null && expression.ParentBinding.Path != null ? expression.ParentBinding.Path.Path : null;
                var sourceValue = sourceItem.GetType().GetProperty(propertyName).GetValue(sourceItem, null);

                // TODO: do validation logic based on sourceItem, propertyName and sourceValue.
            }
        }

        return ValidationResult.ValidResult;
    }
}

Respondido el 12 de junio de 12 a las 09:06

I think I didnt really understand you solution. You are saying that in the ValidationRule class I can do something like "BindingOperations.GetBindingExpression(target,property)" ? - Louro

And can I access another property from the Window DataContext besides the one that is being validated? - Louro

I figured out how to do it, I cast the source item to my viewmodel class and then got the Property. I don't know if this is the correct way to do it, but it tottaly works. Your solution seems to be the cleaner i've seen. Thank you very much. - Louro

Actually, DataErrorValidationRule works almost exactly as the RiskCodeValidation that I posted. It justs casts sourceItem to IDataErrorInfo and gets error string from IDataErrorInfo indexer by passing propertyName. So I suggest you implement IDataErrorInfo on your viewmodel class, and put your validation logic in there, if your errors are just simple strings. I think this would be the cleanest solution. - Stipo

I was going to a known limitation of WPF ValidationRules. I can't bind a dependency property do the ValidationRules' property. This problem is explained and solved (still ugly solution due to the WPF's limitations) here:

http://michlg.wordpress.com/2010/01/29/wpf-custom-validationrule-with-an-additional-parameter/

http://www.codeproject.com/Articles/18678/Attaching-a-Virtual-Branch-to-the-Logical-Tree-in

http://www.11011.net/wpf-binding-properties

or simply use System.ComponentModel.IDataErrorInfo - going to follow this one now.

Respondido el 12 de junio de 12 a las 08:06

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.