WPF Expander Validation
Does anyone know of a way to change the style of an expander if a IDataError validation occurs in a control held within the expander. E.g.
<Expander Header="Details">
<TextBox Text="{Binding Brand.DESCRIPTION,
开发者_Python百科 UpdateSourceTrigger=LostFocus,
ValidatesOnDataErrors=True}"/>
</Expander>
So if the textbox has an error the style of my expander will change (go red maybe). I'm looking to make this as generic as possible so without binding to each control within the expander manually if possible.
You could make use of the Attached Event Validation.Error
(which is raised everytime a validation error is added or removed) through an Attached Behavior. To make this work you need to add NotifyOnValidationError=True
to the bindings.
This Attached Behavior, ChildValidation
, subscribes to the Validation.Error
event for the Expander
which is bubbled up if NotifyOnValidationError
is set to True on the bindings. Since several Control
s may be located within the Expander
it also need to keep track of the count of Validation Errors that's currently active to determine if a Red Border should be displayed or not. It could look like this
Xaml
<Expander Header="Details"
behaviors:ChildValidationBehavior.ChildValidation="True">
<TextBox Text="{Binding Brand.DESCRIPTION,
UpdateSourceTrigger=LostFocus,
ValidatesOnDataErrors=True,
NotifyOnValidationError=True}"/>
</Expander>
ChildValidationBehavior
public static class ChildValidationBehavior
{
private static readonly DependencyProperty ErrorCountProperty =
DependencyProperty.RegisterAttached("ErrorCount",
typeof(int),
typeof(ChildValidationBehavior));
private static void SetErrorCount(DependencyObject element, int value)
{
element.SetValue(ErrorCountProperty, value);
}
private static int GetErrorCount(DependencyObject element)
{
return (int)element.GetValue(ErrorCountProperty);
}
public static readonly DependencyProperty ChildValidationProperty =
DependencyProperty.RegisterAttached("ChildValidation",
typeof(bool),
typeof(ChildValidationBehavior),
new UIPropertyMetadata(false, OnChildValidationPropertyChanged));
public static bool GetChildValidation(DependencyObject obj)
{
return (bool)obj.GetValue(ChildValidationProperty);
}
public static void SetChildValidation(DependencyObject obj, bool value)
{
obj.SetValue(ChildValidationProperty, value);
}
private static void OnChildValidationPropertyChanged(DependencyObject dpo,
DependencyPropertyChangedEventArgs e)
{
Control control = dpo as Control;
if (control != null)
{
if ((bool)e.NewValue == true)
{
SetErrorCount(control, 0);
Validation.AddErrorHandler(control, Validation_Error);
}
else
{
Validation.RemoveErrorHandler(control, Validation_Error);
}
}
}
private static void Validation_Error(object sender, ValidationErrorEventArgs e)
{
Control control = sender as Control;
if (e.Action == ValidationErrorEventAction.Added)
{
SetErrorCount(control, GetErrorCount(control)+1);
}
else
{
SetErrorCount(control, GetErrorCount(control)-1);
}
int errorCount = GetErrorCount(control);
if (errorCount > 0)
{
control.BorderBrush = Brushes.Red;
}
else
{
control.ClearValue(Control.BorderBrushProperty);
}
}
}
精彩评论