【问题标题】:Accessing WPF control validation rules from code从代码访问 WPF 控件验证规则
【发布时间】:2011-05-15 12:44:10
【问题描述】:

XAML:

绑定> 文本框>

代码:

无效按钮OK_Click(对象发送者,RoutedEventArgs e) { // 这里需要知道textboxMin验证是否OK // textboxMin. ??? // 我需要这样写: // if ( textboxMin.Validation.HasErrors ) // 返回; }

如果至少有一个对话框控件未通过验证 - 在 XAML 中,使用绑定,如果知道如何禁用“确定”按钮也将很高兴。有了这种方式,我就不需要在代码中检查验证状态了。

【问题讨论】:

  • 您是否需要知道特定的 ValidationRule 是否有错误或 TextBox 是否有错误?

标签: wpf validation binding


【解决方案1】:

Validation.HasError 是一个附加属性,因此您可以像这样检查它的 textboxMin

void buttonOK_Click(object sender, RoutedEventArgs e)
{
    if (Validation.GetHasError(textboxMin) == true)
         return;
}

要在后面的代码中运行 TextProperty 的所有 ValidationRules,您可以获取 BindingExpression 并调用 UpdateSource

BindingExpression be = textboxMin.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();

更新

如果发生任何验证,将需要一些步骤来实现禁用按钮的绑定。

首先,确保所有绑定都添加 NotifyOnValidationError="True"。示例

<TextBox Name="textboxMin">
    <TextBox.Text>
        <Binding Path="Max" NotifyOnValidationError="True">
            <Binding.ValidationRules>
                <local:IntValidator/>
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

然后我们将一个 EventHandler 连接到 Window 中的 Validation.Error 事件。

<Window ...
        Validation.Error="Window_Error">

在后面的代码中,我们在 observablecollection 中添加和删除验证错误,因为它们来来去去

public ObservableCollection<ValidationError> ValidationErrors { get; private set; } 
private void Window_Error(object sender, ValidationErrorEventArgs e)
{
    if (e.Action == ValidationErrorEventAction.Added)
    {
        ValidationErrors.Add(e.Error);
    }
    else
    {
        ValidationErrors.Remove(e.Error);
    }
}

然后我们可以像这样将Button的IsEnabled绑定到ValidationErrors.Count

<Button ...>
    <Button.Style>
        <Style TargetType="Button">
            <Setter Property="IsEnabled" Value="False"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding ValidationErrors.Count}" Value="0">
                    <Setter Property="IsEnabled" Value="True"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

【讨论】:

  • 第一个版本 - Validation.HasError 未编译。编辑后,GetHasError 正常并给出预期结果。谢谢。
  • 为此目的使用 AttachedProperty 或 Behavior 要好得多,但感谢您提到 NotifyOnValidationError 必须设置为 true!
【解决方案2】:

获取规则前需要先获取Binding

    Binding b=  BindingOperations.GetBinding(textboxMin,TextBox.TextProperty);
    b.ValidationRules

否则您可以使用 BindingExpression 并检查 HasError 属性

 BindingExpression be1 = BindingOperations.GetBindingExpression (textboxMin,TextBox.TextProperty);

be1.HasError

【讨论】:

  • BindingOperations.GetBindingExpression(textBoxMin, TextBox.TextProperty).HasError 成功了。
【解决方案3】:

非常感谢 Fredrik Hedblad 的解决方案。它也帮助了我。我也同意 Lukáš Koten 的观点,即最好将其用作一种行为。这样一来,视图层中就不会混合应用程序逻辑,并且视图模型不必担心复制验证只是为了简单地将其放在那里。这是我的行为版本:

正如 Fredrik Hedblad 所说,首先确保任何控件验证具有绑定属性 NotifyOnValidationError="True"。

这是视图逻辑...更简单...

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

然后在 Window 开始标签下

    Height="Auto" Width="Auto">
<i:Interaction.Behaviors>
    <behavior:ValidationErrorMappingBehavior HasValidationError="{Binding IsInvalid, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</i:Interaction.Behaviors

然后对于按钮,只需像平常一样绑定命令。我们将使用基本的视图模型绑定原则通过 RelayCommand 禁用它。

<Button x:Name="OKButton" Content="OK" Padding="5,0" MinWidth="70" Height="23"
                HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="5,5,0,0"
                Command="{Binding OKCommand}"/>

现在是视图模型及其基本属性和命令

    private bool _isInvalid = false;
    public bool IsInvalid
    {
        get { return _isInvalid; }
        set { SetProperty<bool>(value, ref _isInvalid); }
    }

    private ICommand _okCommand;
    public ICommand OKCommand
    {
        get
        {
            if (_okCommand == null)
            {
                _okCommand = new RelayCommand(param => OnOK(), canparam => CanOK());
            }

            return _okCommand;
        }
    }

    private void OnOK()
    {
        //  this.IsInvalid = false, so we're good... let's just close
        OnCloseRequested();
    }

    private bool CanOK()
    {
        return !this.IsInvalid;
    }

现在,行为

using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;

namespace UI.Behavior
{
public class ValidationErrorMappingBehavior : Behavior<Window>
{
    #region Properties

    public static readonly DependencyProperty ValidationErrorsProperty = DependencyProperty.Register("ValidationErrors", typeof(ObservableCollection<ValidationError>), typeof(ValidationErrorMappingBehavior), new PropertyMetadata(new ObservableCollection<ValidationError>()));

    public ObservableCollection<ValidationError> ValidationErrors
    {
        get { return (ObservableCollection<ValidationError>)this.GetValue(ValidationErrorsProperty); }
        set { this.SetValue(ValidationErrorsProperty, value); }
    }

    public static readonly DependencyProperty HasValidationErrorProperty = DependencyProperty.Register("HasValidationError", typeof(bool), typeof(ValidationErrorMappingBehavior), new PropertyMetadata(false));

    public bool HasValidationError
    {
        get { return (bool)this.GetValue(HasValidationErrorProperty); }
        set { this.SetValue(HasValidationErrorProperty, value); }
    }

    #endregion

    #region Constructors

    public ValidationErrorMappingBehavior()
        : base()
    { }

    #endregion

    #region Events & Event Methods

    private void Validation_Error(object sender, ValidationErrorEventArgs e)
    {
        if (e.Action == ValidationErrorEventAction.Added)
        {
            this.ValidationErrors.Add(e.Error);
        }
        else
        {
            this.ValidationErrors.Remove(e.Error);
        }

        this.HasValidationError = this.ValidationErrors.Count > 0;
    }

    #endregion

    #region Support Methods

    protected override void OnAttached()
    {
        base.OnAttached();
        Validation.AddErrorHandler(this.AssociatedObject, Validation_Error);
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        Validation.RemoveErrorHandler(this.AssociatedObject, Validation_Error);
    }

    #endregion
  }
}

【讨论】:

    猜你喜欢
    • 2023-03-25
    • 1970-01-01
    • 2013-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-30
    • 1970-01-01
    • 2022-11-30
    相关资源
    最近更新 更多