WPF 扩展器验证

发布于 2024-10-16 14:37:11 字数 374 浏览 2 评论 0原文

如果扩展器中的控件中发生 IDataError 验证,有谁知道如何更改扩展器的样式。例如

<Expander Header="Details">
    <TextBox Text="{Binding Brand.DESCRIPTION,
                            UpdateSourceTrigger=LostFocus,
                            ValidatesOnDataErrors=True}"/>
</Expander>

,如果文本框有错误,我的扩展器的样式将会改变(可能会变成红色)。 我希望使其尽可能通用,以便尽可能不手动绑定到扩展器中的每个控件。

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,
                            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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一个人的夜不怕黑 2024-10-23 14:37:11

您可以通过附加行为使用附加事件 Validation.Error (每次添加或删除验证错误时都会引发该事件)。要实现此功能,您需要将 NotifyOnValidationError=True 添加到绑定中。

此附加行为 ChildValidation 订阅 ExpanderValidation.Error 事件,如果 NotifyOnValidationError 则该事件会冒泡在绑定上设置为 True。由于多个 Control 可能位于 Expander 内,因此它还需要跟踪当前活动的验证错误计数,以确定是否应显示红色边框。它可能看起来像这样

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

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 Controls 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);
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文