使用WPF验证规则并禁用“保存”按钮

时间:2008-10-23 19:13:55

标签: wpf validation validationrules

我有一个页面,在单击“保存”按钮之前,几个文本框不能为空。

<TextBox...

                <TextBox.Text>
                    <Binding Path ="LastName" UpdateSourceTrigger="PropertyChanged">

                        <Binding.ValidationRules>
                            <local:StringRequiredValidationRule />
                        </Binding.ValidationRules>                              
                    </Binding>
                </TextBox.Text>

我的规则有效。我的文本框周围有一个红色边框,直到我输入一个值。所以现在我想将此验证规则添加到我的其他文本框中。

现在,如何在页面没有错误之前禁用“保存”按钮?我不知道要检查什么是否有任何验证错误。

10 个答案:

答案 0 :(得分:17)

答案 1 :(得分:15)

在视图的代码隐藏中,您可以像这样连接Validation.ErrorEvent;

this.AddHandler(Validation.ErrorEvent,new RoutedEventHandler(OnErrorEvent)); 

然后

private int errorCount;
private void OnErrorEvent(object sender, RoutedEventArgs e)
{
    var validationEventArgs = e as ValidationErrorEventArgs;
    if (validationEventArgs  == null)
        throw new Exception("Unexpected event args");
    switch(validationEventArgs.Action)
    {
        case ValidationErrorEventAction.Added:
            {
                errorCount++; break;
            }
        case ValidationErrorEventAction.Removed:
            {
                errorCount--; break;
            }
        default:
            {
                throw new Exception("Unknown action");
            }
    }
    Save.IsEnabled = errorCount == 0;
}

这假设您将收到删除通知(如果您删除有问题的元素,则不会发生这种情况。)

答案 2 :(得分:8)

您想使用附加属性Validation.HasError

Josh Smith在Binding to (Validation.Errors)[0] without Creating Debug Spew上有一个有趣的读物。

答案 3 :(得分:3)

int count = 0;

private void LayoutRoot_BindingValidationError(object sender, ValidationErrorEventArgs e)
{
    if (e.Action == ValidationErrorEventAction.Added)
    {
        button1.IsEnabled = false;
        count++;
    }
    if (e.Action == ValidationErrorEventAction.Removed)
    {                
        count--;
        if (count == 0) button1.IsEnabled = true;
    }
}

答案 4 :(得分:2)

这是一个帮助器方法,它跟踪依赖项对象(及其所有子代)的验证错误,并调用委托来通知有关更改。它还跟踪删除有验证错误的孩子。

 public static void AddErrorHandler(DependencyObject element, Action<bool> setHasValidationErrors)
        {
            var errors = new List<Tuple<object, ValidationError>>();

            RoutedEventHandler sourceUnloaded = null;

            sourceUnloaded = (sender, args) =>
                {
                    if (sender is FrameworkElement)
                        ((FrameworkElement) sender).Unloaded -= sourceUnloaded;
                    else
                        ((FrameworkContentElement) sender).Unloaded -= sourceUnloaded;

                    foreach (var error in errors.Where(err => err.Item1 == sender).ToArray())
                        errors.Remove(error);

                    setHasValidationErrors(errors.Any());
                };

            EventHandler<ValidationErrorEventArgs> errorHandler = (_, args) =>
                {
                    if (args.Action == ValidationErrorEventAction.Added)
                    {
                        errors.Add(new Tuple<object, ValidationError>(args.OriginalSource, args.Error));

                        if (args.OriginalSource is FrameworkElement)
                            ((FrameworkElement)args.OriginalSource).Unloaded += sourceUnloaded;
                        else if (args.OriginalSource is FrameworkContentElement)
                            ((FrameworkContentElement)args.OriginalSource).Unloaded += sourceUnloaded;
                    }
                    else
                    {
                        var error = errors
                            .FirstOrDefault(err => err.Item1 == args.OriginalSource && err.Item2 == args.Error);

                        if (error != null) 
                            errors.Remove(error);
                    }

                    setHasValidationErrors(errors.Any());
                };


            System.Windows.Controls.Validation.AddErrorHandler(element, errorHandler);
        } 

答案 5 :(得分:2)

就是这样 您需要从代码行为

中检查HasError控件属性

并在保存按钮中单击

执行此代码
 BindingExpression bexp = this.TextBox1.GetBindingExpression(TextBox.TextProperty);
bexp.UpdateSource(); // this to refresh the binding and see if any error exist 
bool hasError = bexp.HasError;  // this is boolean property indique if there is error 

MessageBox.Show(hasError.ToString());

答案 6 :(得分:1)

只需从System.ComponentModel.IDataErrorInfo中获取ViewModel以进行验证 从INotifyPropertyChanged到通知按钮

make property:

    public bool IsValid
    {
        get
        {
            if (this.FloorPlanName.IsEmpty())
                return false;
            return true;
        }
    }

在xaml中,将其连接到按钮

<Button Margin="4,0,0,0" Style="{StaticResource McVMStdButton_Ok}" Click="btnDialogOk_Click" IsEnabled="{Binding IsValid}"/>

在IDataErrorInfo覆盖中,通知btutton

public string this[string columnName]{
        get
        {
            switch (columnName)
            {
                case "FloorPlanName":
                    if (this.FloorPlanName.IsEmpty())
                    {
                        OnPropertyChanged("IsValid");
                        return "Floor plan name cant be empty";
                    }
                    break;
            }
        }
}

答案 7 :(得分:1)

我已尝试过上述几种解决方案;然而,他们都没有为我工作。

我的简单问题

我有一个简单的输入窗口,要求用户提供URI,如果TextBox值不是有效Uri,则应禁用Okay按钮。

我的简单解决方案

这对我有用:

CommandBindings.Add(new CommandBinding(AppCommands.Okay,
            (sender, args) => DialogResult = true,
            (sender, args) => args.CanExecute = !(bool) _uriTextBoxControl.GetValue(Validation.HasErrorProperty)));

答案 8 :(得分:0)

因为它仍然丢失,因此如果链接消失了,请改用开发人员的答案:

XAML:

<TextBox.Text Validation.Error="handleValidationError">
    <Binding Path ="LastName" 
             UpdateSourceTrigger="PropertyChanged"
             NotifyOnValidationError="True">
        <Binding.ValidationRules>
            <local:StringRequiredValidationRule />
        </Binding.ValidationRules>                              
    </Binding>
</TextBox.Text>
<Button IsEnabled="{Binding HasNoValidationErrors}"/>

CodeBehind / C#:

private int _numberOfValidationErrors;
public bool HasNoValidationErrors => _numberOfValidationErrors = 0;

private void handleValidationError(object sender, ValidationErrorEventArgs e)
{
    if (e.Action == ValidationErrorEventAction.Added)
        _numberOfValidationErrors++;
    else
        _numberOfValidationErrors--;
}

答案 9 :(得分:0)

此网站包含您要查找的代码: https://www.wpfsharp.com/2012/02/03/how-to-disable-a-button-on-textbox-validationerrors-in-wpf/

对于后代,如果在输入字段上使用ValidationRule覆盖,则按钮代码应如下所示:

<Button Content="<NameThisButton>" Click="<MethodToCallOnClick>" >
                <Button.Style>
                    <Style TargetType="{x:Type Button}">
                        <Setter Property="IsEnabled" Value="false" />
                        <Style.Triggers>
                            <MultiDataTrigger>
                                <MultiDataTrigger.Conditions>                                    
                                    <Condition Binding="{Binding ElementName=<TextBoxName>, Path=(Validation.HasError)}" Value="false" />
                                    <Condition Binding="{Binding ElementName=<TextBoxName>, Path=(Validation.HasError)}" Value="false" />
                                </MultiDataTrigger.Conditions>
                                <Setter Property="IsEnabled" Value="true" />
                            </MultiDataTrigger>
                        </Style.Triggers>
                    </Style>
                </Button.Style>
            </Button>