I have a class that is composed of a method called validate and two properties, IsValid and Errors. Which help me with checking the validation of a panel, window, or UserControl repectively on submit and if errors, show a message box to correct the errors for save the form, if no errors. This code works wonderfully with the standard WPF controls, but for some unknown reason, does not read any of the XamEditors even though the error exists and is showing the appropriate error control template on the form. So able to apply a Validation Rule and it works fine and shows the appropriate Validation.ErrorTemplate for the XamEditor. But when I run the code below on a click event, the code below does not find the errors. I am baffled, because my rule validators work on the standard WPF controls and the XamEditor controls, the code that I validate the form with only picks up the standard WPF control Validation.Errors. The class and code that I am running is below:
private void cmdSubmit_Click(object sender, RoutedEventArgs e) { _validator.Validate(grpMasterDetails);
if (_validator.Errors.Count > 0) { MessageBox.Show("Invalid", "Invalid", MessageBoxButton.OK, MessageBoxImage.Error); //invalid } else { //valid\ MessageBox.Show("Valid", "Valid", MessageBoxButton.OK, MessageBoxImage.Exclamation); } }
Now the class that does all the work:
public class Validator { private readonly List<String> _errors = new List<String>(); private bool _isValid;
public List<String> Errors { get { return _errors; } }
public bool IsValid { get { return _isValid; } }
public void Validate(DependencyObject content) { _isValid = true; _errors.Clear(); ValidateDependencyObject(content); }
private void ValidateDependencyObject(DependencyObject element) { foreach (object childElement in LogicalTreeHelper.GetChildren(element)) { if (childElement is DependencyObject) ValidateDependencyObject((DependencyObject)childElement); }
ValidateBindings(element); }
private void ValidateBindings(DependencyObject element) { Type elementType = element.GetType();
FieldInfo[] dependencyPropertyFields = elementType.GetFields( BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly);
foreach (FieldInfo dependencyPropertyField in dependencyPropertyFields) { ValidatePropertyBinding(element, dependencyPropertyField); } }
private void ValidatePropertyBinding(DependencyObject element, FieldInfo dependencyPropertyField) { var dependencyProperty = dependencyPropertyField.GetValue(element) as DependencyProperty; if (dependencyProperty == null) return;
Binding binding = BindingOperations.GetBinding(element, dependencyProperty); if (binding == null) return;
foreach (ValidationRule rule in binding.ValidationRules) { ValidationResult result = rule.Validate(element.GetValue(dependencyProperty), CultureInfo.CurrentCulture);
if (!result.IsValid) _errors.Add(result.ErrorContent.ToString()); _isValid &= result.IsValid; }
ResetValidationError(element, dependencyProperty); }
private void ResetValidationError(DependencyObject element, DependencyProperty dependencyProperty) { var control = element as Control; if (control == null) return;
BindingExpression bindingExpression = control.GetBindingBLOCKED EXPRESSION; } }
Please help me with this issue.
I changed my BindingFlags enum to BindingFlags.FlattenHierarcy and all works well, thank you for your input.
I tried taking that Binding Flag, BindingFlags.DeclaredOnly out, and my code is still not picking up the errors in the base ValueEditor class.
Correct, I am not getting any FiedInfo for the properties bound to the XamEditors. What binding should I use that will pick up the values in the base ValueEditor class.
Well in reading through your code it looks like you're only going to pick up the properties declared by the derived class type (because you're using the DeclaredOnly binding flag). Have you checked that you are actually getting a FieldInfo for the property in question? I'm guessing you're using the Value and/or Text property and both of these are defined on the base ValueEditor class.