在下面的XAML中,我使用MultiDataTrigger和ValidationRule试图保持提交按钮disabled
,直到两个文本框中输入了有效值(字母数字(。这工作得很好,因为当值无效(例如some@test
(时,按钮会被禁用,当您使该值有效(例如sometest
(时,它会启用该按钮。
问题:但当您启动应用程序时,它会将按钮显示为Enabled(已启用(,这会破坏整个目的,因为即使您尚未开始输入文本框值,也可以提交按钮。
问题:我可能缺少什么,我们如何解决?
备注:如果您查看(并且我测试了(上面第一个链接中的MultiDataTrigger
示例,您会注意到(如图所示(初始值(如预期(显示为Unverified
和red
颜色,当您选中这两个复选框时,文本值变为Verified
和绿色。所以,我似乎明显遗漏了上面XAML中的一些内容。请注意,我已将按钮的初始状态设置为<Setter Property="IsEnabled" Value="False"/>
。
<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:
public class MyDataSource
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
AlphanumericOnlyValidationRule.cs
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的MultiDataTrigger.Conditions
块中的值Validation.HasError
假定没有验证错误(因为应用程序刚刚加载,用户尚未采取任何操作(,因此它再次启用提交按钮。这只是我基于以下XAML的观察结果,我通过修改如下所示的MultiDataTrigger示例使用了该XAML。在这里,我刚刚将TextBlock
和相应的值一起更改为Button
,并注意到最初该按钮是禁用的(因为默认情况下复选框是未选中的(,当您同时选中这两个复选框时,按钮会被启用(正如预期的那样(。因此,我们可能需要看看(在上面的XAML中(如何在应用程序初始加载时禁用按钮。
从联机修改XAMLMiltiDataTrigger示例:
<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>
由于验证发生,这是预期行为
(…(当目标的值传输到绑定源时所有物
源
在您的情况下,要在更新控件的值之前强制验证,您可以将ValidatesOnTargetUpdated="True"
属性添加到ValidationRule
,它将在更新绑定的目标时触发验证。
<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>
验证规则。验证目标已更新-MS DOC