我们的应用程序中有几个数据对象最终绑定到网格。我们让他们实现了IDataErrorInfo接口,这样通过向属性添加错误消息,我们看到了rowheader更改样式,DataGridCells获得了红色边框。一切都很好。
我们现在有一个额外的要求,我们有错误和警告,而不仅仅是错误。警告与错误相同,只是它们应该产生黄色边框而不是红色边框。
我们基于IDataErrorInfo创建了一个新的接口IDataWarningInfo。工作良好。我可以在运行时访问它,我有能够访问它的RowValidatiionRules,并设置黄色行标题而不是红色标题,相应的工具提示等。我缺少的是设置给定单元格边框的能力为黄色,因为它被数据绑定到属性,其中该属性具有警告消息。
我可以通过将数据绑定属性的名称传递回接口来检索该警告消息;我怀疑在底层,验证代码正是这样做的。我缺少的是如何在XAML中做到这一点。具体来说,我认为我需要将一个Style应用于一个单元格,其中该Style包含一个DataTrigger,它以某种方式将对象的名称传递给DataBound属性,然后如果结果与null不同,则将一些Setter应用于Cell
有谁知道如何实现这个目标?
答案 0 :(得分:2)
我有一个带有附加属性的类,要验证的依赖项属性。然后它使用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);
}
}