我有一个带有附加属性的类,需要验证该属性的依赖属性。然后,它使用 DependencyPropertyDescriptor 将事件附加到该 dependencyproperty 的更改事件。
然后,当它发生更改时,它会查看绑定,运行验证规则并设置属性的验证错误,而不提交绑定。
public static class ValidatingControlBehavior
{
/// <summary>
/// Defines the ValidatingProperty dependency property.
/// </summary>
public static readonly DependencyProperty ValidatingPropertyProperty = DependencyProperty.RegisterAttached("ValidatingProperty", typeof(DependencyProperty), typeof(ValidatingControlBehavior),
new PropertyMetadata(ValidatingControlBehavior.ValidatingPropertyProperty_PropertyChanged));
/// <summary>
/// Attaches the event.
/// </summary>
/// <param name="control">The control.</param>
/// <param name="dependencyProperty">The dependency property.</param>
private static void AttachEvent(Control control, DependencyProperty dependencyProperty)
{
DependencyPropertyDescriptor.FromProperty(dependencyProperty, typeof(Control)).AddValueChanged(control, ValidatingControlBehavior.Control_PropertyChanged);
control.ForceValidation(dependencyProperty);
}
/// <summary>
/// Handles the PropertyChanged event of the Control control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private static void Control_PropertyChanged(object sender, EventArgs e)
{
Control control = (Control)sender;
control.ForceValidation(ValidatingControlBehavior.GetValidatingProperty(control));
}
/// <summary>
/// Forces the validation.
/// </summary>
/// <param name="dependencyObject">The dependency object.</param>
/// <param name="dependencyProperty">The dependency property.</param>
private static void ForceValidation(this DependencyObject dependencyObject, DependencyProperty dependencyProperty)
{
BindingExpressionBase expression = BindingOperations.GetBindingExpressionBase(dependencyObject, dependencyProperty);
Collection<ValidationRule> validationRules;
if (expression != null)
{
MultiBinding multiBinding;
Binding binding = expression.ParentBindingBase as Binding;
if (binding != null)
{
validationRules = binding.ValidationRules;
}
else if ((multiBinding = expression.ParentBindingBase as MultiBinding) != null)
{
validationRules = multiBinding.ValidationRules;
}
else
{
return;
}
for (int i = 0; i < validationRules.Count; i++)
{
ValidationRule rule = validationRules[i];
ValidationResult result = rule.Validate(dependencyObject.GetValue(dependencyProperty), CultureInfo.CurrentCulture);
if (!result.IsValid)
{
Validation.MarkInvalid(expression, new ValidationError(rule, expression.ParentBindingBase, result.ErrorContent, null));
return;
}
}
Validation.ClearInvalid(expression);
}
}
/// <summary>
/// Detaches the event.
/// </summary>
/// <param name="control">The control.</param>
/// <param name="dependencyProperty">The dependency property.</param>
private static void DetachEvent(Control control, DependencyProperty dependencyProperty)
{
DependencyPropertyDescriptor.FromProperty(dependencyProperty, typeof(Control)).RemoveValueChanged(control, ValidatingControlBehavior.Control_PropertyChanged);
}
/// <summary>
/// Handles the PropertyChanged event of the ValidatingPropertyProperty control.
/// </summary>
/// <param name="d">The source of the event.</param>
/// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void ValidatingPropertyProperty_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Control control = d as Control;
if (control != null)
{
if (e.OldValue != null)
{
ValidatingControlBehavior.DetachEvent(control, (DependencyProperty)e.OldValue);
}
if (e.NewValue != null)
{
ValidatingControlBehavior.AttachEvent(control, (DependencyProperty)e.NewValue);
}
}
}
/// <summary>
/// Gets the validating property.
/// </summary>
/// <param name="control">The control.</param>
/// <returns>
/// Dependency property.
/// </returns>
public static DependencyProperty GetValidatingProperty(Control control)
{
return (DependencyProperty)control.GetValue(ValidatingControlBehavior.ValidatingPropertyProperty);
}
/// <summary>
/// Sets the validating property.
/// </summary>
/// <param name="control">The control.</param>
/// <param name="validatingProperty">The validating property.</param>
public static void SetValidatingProperty(Control control, DependencyProperty validatingProperty)
{
control.SetValue(ValidatingControlBehavior.ValidatingPropertyProperty, validatingProperty);
}
}