在验证错误时禁用按钮

30

我有几个带有自定义验证器的文本框:
(如果发送回对象的数据“错误”,我并不介意(该属性是字符串),我只需要防止在出现错误时按钮的功能,所以如果绑定不是那种验证的正确位置,请告诉我。我只喜欢可以使用Validation.ErrorTemplate支持的验证.ErrorTemplate)

<ControlTemplate x:Key="validator" >
    <DockPanel LastChildFill="True">
       <TextBlock DockPanel.Dock="Right" Foreground="Red" FontSize="12pt">!</TextBlock>
       <Border BorderBrush="Red" BorderThickness="1.0">
            <AdornedElementPlaceholder />
       </Border>
    </DockPanel>
</ControlTemplate>

<TextBox Height="23" Width="150"  TextWrapping="Wrap"
         Validation.ErrorTemplate="{StaticResource validator}">
         <TextBox.Text>
            <Binding Path="StringProperty" UpdateSourceTrigger="LostFocus">
               <Binding.ValidationRules>
                   <local:NumbersOnly/>
               </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
</TextBox>

如果出现任何验证错误,我该如何禁用特定的按钮?

<Button Content="DO Work"  Height="57" HorizontalAlignment="Left"  Name="button1" VerticalAlignment="Top" Width="234" Click="button1_Click" />

可能是重复问题:https://dev59.com/GHVC5IYBdhLWcg3woStW - Damascus
2
那边的帖子并没有回答这个问题... - anderi
5个回答

67

您可以在ButtonStyle.Triggers中使用MultiDataTrigger属性。假设我们有一个名为“txtName”的TextBox,当TextBox验证错误时,我们必须禁用按钮“btnSave”。

您可以这样做:

<Button Content="Save" 
        Grid.Column="1"
        Grid.Row="3"
        HorizontalAlignment="Right"
        Height="23" 
        Name="btnSave" 
        Width="75"
        IsDefault="True"
        Command="{Binding SaveProtocolCommand}"
        Margin="3">
  <Button.Style>
    <Style TargetType="Button">
      <Setter Property="IsEnabled" Value="False"/>
      <Style.Triggers>
        <MultiDataTrigger>
          <MultiDataTrigger.Conditions>
            <Condition Binding="{Binding Path=(Validation.HasError), ElementName=txtName}" Value="False"/>
          </MultiDataTrigger.Conditions>
          <Setter Property="IsEnabled" Value="True"/>
        </MultiDataTrigger>
      </Style.Triggers>
    </Style>
  </Button.Style>
</Button>

希望这能对你有所帮助。


13
如果有其他人和我一样不知道,你必须在 Validation.HasError 路径周围加上括号才能引用该附加属性。没有括号,你就会像我一样得到一个“System.Windows.Data Warning: 40 : BindingExpression path error”警告。请参考链接:https://dev59.com/2mYq5IYBdhLWcg3wkRUo#14382796。 - DJH
2
@S.Mishra 如果我有两个文本框怎么办? 编辑:算了。只需添加几乎相同的行条件绑定即可。 - p__d
1
@p__d 我相信你可以在 <MultiDataTrigger.Conditions> 部分下添加更多的 <Condition>。每个输入控件都需要一个。 - S.Mishra
1
那么,如果我有一个带有验证的 n 个文本框的 ItemsControl 呢? - Ignatii Marine
@S.Mishra,您提出的解决方案会在出现错误时禁用按钮。我们希望默认情况下按钮保持禁用状态,一旦条件满足,它就会变为可用状态。目前,即使文本框中没有输入任何内容,您也允许提交按钮。您如何实现我刚才描述的场景? - nam

13

CanExecute 在 MVVM 中用于授权管理,但人们也会将其用于验证。最好的方法是在 XAML 中完成。如果您有多个字段需要验证,则需要使用转换器(InverseAndBooleansToBooleanConverter 是我实现的用于多个布尔值的转换器)。下面是如何实现:

XAML 代码(如果 XAML 代码未显示,请见谅,因为即使我尝试了,它也可能不会出现):

<Button Name="Button_Test" Content="Test">
    <Button.IsEnabled>
        <MultiBinding Converter="{StaticResource InverseAndBooleansToBooleanConverter}" Mode="TwoWay">
            <Binding ElementName="TextBox_Field1" Path="(Validation.HasError)" />
            <Binding ElementName="TextBox_Field2" Path="(Validation.HasError)" />
            <Binding ElementName="TextBox_Field3" Path="(Validation.HasError)" />
        </MultiBinding>
    </Button.IsEnabled>
</Button>

转换器

public class InverseAndBooleansToBooleanConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (values.LongLength > 0)
        {
            foreach (var value in values)
            {
                if (value is bool && (bool)value)
                {
                    return false;
                }
             }
        }    
        return true;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
            throw new NotImplementedException();
    }
}

运行得很好。喜欢这个解决方案。 - JMIII

3

将以下代码添加到您的TextBlock中:

Validation.Error="Save_Error"

CodeBehind (xaml.cs):

public partial class MyView : Window
{
    private int _noOfErrorsOnScreen = 0;

    public MyView()
    {
        InitializeComponent();
    }


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

        Save.IsEnabled = _noOfErrorsOnScreen > 0 ? false : true;

    }
}

0

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接