【问题标题】:Mimicking Validation Behaviour without Validation在没有验证的情况下模仿验证行为
【发布时间】:2011-04-18 07:42:49
【问题描述】:

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

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

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

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

有谁知道如何做到这一点?

【问题讨论】:

    标签: .net wpf validation triggers styles


    【解决方案1】:

    我有一个带有附加属性的类,要验证它的依赖属性。然后它使用 DependencyPropertyDescriptor 将事件附加到该依赖属性的更改事件。

    然后当它发生变化时,它会查看绑定,运行验证规则并为属性设置验证错误,而不提交绑定。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-12
      • 2018-09-21
      • 1970-01-01
      • 2021-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多