模拟没有验证的验证行为 [英] Mimicking Validation Behaviour without Validation

查看:62
本文介绍了模拟没有验证的验证行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们的应用程序中有几个数据对象最终绑定到网格。我们让他们实现IDataErrorInfo接口,以便通过向属性添加错误消息,我们看到行标题更改样式,并且DataGridCells出现红色边框。一切都很好。

We have several data objects in our application that wind up bound to grids. We have them implementing the IDataErrorInfo interface, so that by adding error messages to the properties, we see the rowheader change style and the DataGridCells gain a red border. All well and good.

我们现在有一个附加要求,即不仅仅是错误,我们还要有错误和警告。警告与错误相同,只是警告应该产生黄色边框而不是红色边框。

We now have an additional requirement that rather than merely having Errors, we have Errors and Warnings. Warnings are identical to errors except that they should produce a yellow border instead of a red one.

我们基于IDataErrorInfo创建了一个新接口IDataWarningInfo。工作良好。我可以在运行时访问它,我具有可以访问它的RowValidatiionRules,并设置黄色行标题而不是红色行标题,适当的工具提示等。我缺少的是设置给定单元格边框的功能变为黄色,这是因为它已绑定到该属性具有警告消息的属性。

We created a new interface, IDataWarningInfo, based on IDataErrorInfo. Works fine. I can access it at runtime, I have RowValidatiionRules that that are able to access it, and set the yellow row header instead of the red one, the appropriate tooltip, etc. What I'm missing is the ability to set a given cell's border to yellow, on the basis that it is databound to a property where that property has a warning message.

我可以通过传递数据绑定属性的名称来检索该警告消息返回界面;我怀疑在背后,验证代码正是在这样做。我所缺少的是如何在XAML中做到这一点。具体来说,我想我需要将一个Style应用于一个单元格,其中该Style包含一个DataTrigger,该DataTrigger会以某种方式将DataBound属性的名称传递给该对象,然后,如果结果不同于null,则将一些Setter应用于该Cell 。

I could retrieve that warning message by passing the name of the databound property back to the interface; I suspect that under the hood, the Validation code is doing exactly that. What I'm missing is how to do that in XAML. Specifically, I think I need to apply a Style to a cell, where that Style contains a DataTrigger that somehow passes to the object the name of the DataBound property, and then if the result is different from null, applies a few Setters to the Cell.

有人知道如何实现吗?

推荐答案

I有一个带有附加属性的类,要验证其依赖项属性。然后,它使用DependencyPropertyDescriptor将事件附加到该dependencyproperty的change事件。

I have a class with an attached property for which dependencyproperty to validate. Then it uses DependencyPropertyDescriptor to attach an event to that dependencyproperty's change event.

然后,当其更改时,它会检查绑定,运行验证规则并设置验证错误

Then when it changes, it looks through the bindings, runs the validation rules and sets the validation errors for the property without commiting the binding.

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);
    }
}

这篇关于模拟没有验证的验证行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆