首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >WPF ValidationRule和DataTrigger禁用提交按钮

WPF ValidationRule和DataTrigger禁用提交按钮
EN

Stack Overflow用户
提问于 2020-11-10 17:40:26
回答 1查看 304关注 0票数 1

在下面的XAML中,我使用MultiDataTriggerValidationRule试图保持提交按钮disabled,直到两个文本框中输入了有效值(字母数字)。它工作得很好,因为当值无效(例如,some@test)按钮被禁用,而当您使该值有效(例如,sometest)时,则启用该按钮。

问题:但是当您启动应用程序时,它会将按钮显示为已启用的按钮--这违背了所有的目的,因为您可以提交该按钮,即使您还没有开始输入文本框值。

问题:我在这里可能缺少了什么,我们如何解决它?

备注:如果您在上面的第一个链接中查看(我测试过) MultiDataTrigger示例,您会注意到(正如两个图像所示),初始值(如预期的那样)显示为带有red颜色的Unverified,而当您选中这两个复选框时,文本值将更改为带绿色的Verified。所以,很明显,我在上面的XAML中遗漏了一些东西。请注意,我已经将按钮的初始状态设置为<Setter Property="IsEnabled" Value="False"/>

代码语言:javascript
运行
复制
<Window x:Class="WPF_DataValidation.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPF_DataValidation"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        
        <local:MyDataSource x:Key="myds"/>

        <ControlTemplate x:Key="ValidationTemplate">
            <DockPanel>
                <TextBlock Text="{Binding [0].ErrorContent}" Foreground="Red" DockPanel.Dock="Bottom" Grid.Row="1"/>
                <AdornedElementPlaceholder/>
            </DockPanel>
        </ControlTemplate>
        <Style TargetType="Label">
            <Setter Property="Margin" Value="5" />
            <Setter Property="VerticalAlignment" Value="Center" />
        </Style>
        <Style x:Key="DefaultTextBoxStyle" TargetType="TextBox">
            <Setter Property="Margin" Value="5" />
            <Setter Property="VerticalAlignment" Value="Center" />
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" SharedSizeGroup="Labels" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Label Name="lblFirstName">First Name:</Label>
        <TextBox Name="txtFirstName" Grid.Column="1" Style="{StaticResource DefaultTextBoxStyle}" Validation.ErrorTemplate="{StaticResource ValidationTemplate}">
            <TextBox.Text>
                <Binding Path="FirstName" Source="{StaticResource myds}" UpdateSourceTrigger="PropertyChanged">
                    <Binding.ValidationRules>
                        <local:AlphanumericOnlyValidationRule/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>

        <Label Name="lblLastName" Grid.Row="1">Last Name:</Label>
        <TextBox Name="txtLastName" Grid.Row="1" Grid.Column="1" Style="{StaticResource DefaultTextBoxStyle}" Validation.ErrorTemplate="{StaticResource ValidationTemplate}">
            <TextBox.Text>
                <Binding Path="LastName" Source="{StaticResource myds}" UpdateSourceTrigger="PropertyChanged">
                    <Binding.ValidationRules>
                        <local:AlphanumericOnlyValidationRule />
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>

        <Button x:Name="btnTest" Content="Test" Grid.Row="2" HorizontalAlignment="Right">
            <Button.Style>
                <Style TargetType="Button">
                    <Setter Property="IsEnabled" Value="False"/>
                    <Style.Triggers>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding Path=(Validation.HasError), ElementName=txtFirstName}" Value="False"/>
                                <Condition Binding="{Binding Path=(Validation.HasError), ElementName=txtLastName}" Value="False"/>
                            </MultiDataTrigger.Conditions>
                            <Setter Property="IsEnabled" Value="True"/>
                        </MultiDataTrigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
        </Button>
    </Grid>
</Window>

MyDataSource.cs

代码语言:javascript
运行
复制
public class MyDataSource
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

AlphanumericOnlyValidationRule.cs

代码语言:javascript
运行
复制
using System.Windows.Controls;
using System.Linq;
using System.Globalization;

namespace WPF_DataValidation
{
    public class AlphanumericOnlyValidationRule: ValidationRule
    {
        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            string sVal = value as string;

            if (string.IsNullOrEmpty(sVal))
            {
                return new ValidationResult(false, "Please enter some text");
            }

            if (!sVal.All(char.IsLetterOrDigit))
            {
                //Note: this will also return false if text has a blank space
                return new ValidationResult(false, "This field must contain alphanumeric characcters only");
            }

            return new ValidationResult(true, null);
        }
    }
}

观测

问题似乎是,当应用程序第一次加载时,它可能第一次禁用提交按钮。但是XAML的Validation.HasError块中的值MultiDataTrigger.Conditions假定没有验证错误(因为应用程序刚刚加载,用户还没有采取任何行动),因此它再次启用提交按钮。这只是我通过修改MultiDataTrigger实例使用的以下XAML的观察结果,如下所示。在这里,我将TextBlock与相应的值一起更改为Button,并注意到最初该按钮被禁用(因为默认情况下不选中复选框),并且当您选中这两个复选框时,按钮将被启用(如预期的那样)。因此,我们可能需要了解(在上面的XAML中),当应用程序最初加载时,我们如何禁用按钮。

从联机 MiltiDataTrigger实例中修改XAML

代码语言:javascript
运行
复制
<Button.Style>
    <Style TargetType="Button">
         <Setter Property="IsEnabled" Value="False"/>
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding Path=(Validation.HasError), ElementName=txtFirstName}" Value="False"/>
                        <Condition Binding="{Binding Path=(Validation.HasError), ElementName=txtLastName}" Value="False"/>
                    </MultiDataTrigger.Conditions>
                  <Setter Property="IsEnabled" Value="True"/>
              </MultiDataTrigger>
            </Style.Triggers>
         </Style>
</Button.Style>
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-11-10 21:25:15

这是预期的行为,因为验证发生了。

(.)当目标的值被传输到绑定源属性时。

来源

在您的示例中,在更新控件的值之前强制进行验证,您可以将ValidatesOnTargetUpdated="True"属性添加到ValidationRule中,并且在更新绑定的目标时它将触发验证。

代码语言:javascript
运行
复制
<TextBox
    Name="txtLastName"
    Grid.Row="1"
    Grid.Column="1"
    Style="{StaticResource DefaultTextBoxStyle}"
    Validation.ErrorTemplate="{StaticResource ValidationTemplate}"
    >
    <TextBox.Text>
        <Binding
            Path="LastName"
            Source="{StaticResource myds}"
            UpdateSourceTrigger="PropertyChanged"
            >
            <Binding.ValidationRules>
                <local:AlphanumericOnlyValidationRule ValidatesOnTargetUpdated="True" />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

ValidationRule.ValidatesOnTargetUpdated - MS

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64773959

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档