为什么我的 WPF ValidationRule 没有被执行?
Why isn't my WPF ValidationRule being executed?
我将不谈大事,但我在窗体上有一个 ComboBox,它't/isn 表现不正常。为了尝试通过实验解决问题,我创建了一个测试 WPF 项目,并将所有相关代码添加到一个简单的 WPF Window.
在我的原始表单中,当 ComboBox 上的 SelectedValue
更改时,我可以根据需要执行 ValidationRule。但是,将代码复制并粘贴到这个新项目后,我可以编译并 运行 程序没有错误,但是我无法让验证程序执行?
可以肯定的是,我在整个代码中都设置了断点。我永远无法在我的 ValidationRule
中使用 Validate(...)
方法,而且我不明白为什么这不起作用。特别是因为这是一个直接复制和粘贴,只为明显的参考需求更新了一些最小的命名空间,这在我原来的应用程序中肯定有效。
以下是所有相关代码。随意复制、粘贴和 运行.
XAML
<Window Height="270"
Title="MainWindow"
Width="532"
x:Class="WPFDataGridApp13.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:my="clr-namespace:WPFDataGridApp13"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<Style TargetType="ComboBox">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>
</Style.Triggers>
</Style>
<ControlTemplate x:Key="validationTemplate">
<Grid>
<Border BorderThickness="1" BorderBrush="Red" >
<AdornedElementPlaceholder />
</Border>
</Grid>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<ComboBox x:Name="myEntityComboBox"
DisplayMemberPath="myEntityName" SelectedValuePath="myEntityId"
Validation.ErrorTemplate="{StaticResource validationTemplate}"
VerticalAlignment="Center" Margin="5">
<ComboBox.SelectedValue>
<Binding Path="myEntityId"
Mode="TwoWay"
NotifyOnValidationError="True"
NotifyOnTargetUpdated="True"
NotifyOnSourceUpdated="True"
ValidatesOnExceptions="True"
ValidatesOnDataErrors="True"
UpdateSourceTrigger="PropertyChanged">
<!--<Binding.ValidationRules>
<my:NonNullValidator/>
</Binding.ValidationRules>-->
</Binding>
</ComboBox.SelectedValue>
</ComboBox>
<Button Content="Select a null value." Click="Button_Click" Margin="5"/>
</StackPanel>
</Window>
Window 代码隐藏
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace WPFDataGridApp13
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
myEntityComboBox.SelectedIndex = 0;
myEntityComboBox.ItemsSource = new[]
{
new { myEntityId = (int?)null, myEntityName="Null Option"},
new { myEntityId = (int?)1, myEntityName="#1"},
new { myEntityId = (int?)2, myEntityName="#2"}
};
Binding b = BindingOperations.GetBinding(myEntityComboBox, ComboBox.SelectedValueProperty);
b.ValidationRules.Clear();
b.ValidationRules.Add(new WPFDataGridApp13.NonNullValidator());
}
private void myEntityComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void Button_Click(object sender, RoutedEventArgs e)
{
myEntityComboBox.SelectedIndex = 0;
}
}
public class NonNullValidator : ValidationRule
{
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
return value == null
? new ValidationResult(false, "Gruu!")
: new ValidationResult(true, null);
}
}
}
快速说明,我的 NotNullValidator
的 XAML 声明是我指定验证器的原始方法,也是我设置此 属性 的首选方法。
我已经将其注释掉并在我的代码隐藏文件中设置了验证器,但这也没有用。无论我尝试什么,我都无法在 NonNullValidator
class 上点击 Validate
方法。
怎么回事?
您的绑定有问题。参考下面的代码。您需要将您选择的组合值绑定到一些 属性.
<Window x:Class="IconicZip_Learning.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:IconicZip_Learning"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<Style TargetType="ComboBox">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>
</Style.Triggers>
</Style>
<ControlTemplate x:Key="validationTemplate">
<Grid>
<Border BorderThickness="1" BorderBrush="Red" >
<AdornedElementPlaceholder />
</Border>
</Grid>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<ComboBox x:Name="myEntityComboBox"
DisplayMemberPath="myEntityName" SelectedValuePath="myEntityId"
Validation.ErrorTemplate="{StaticResource validationTemplate}"
VerticalAlignment="Center" Margin="5">
<ComboBox.SelectedValue>
<Binding Path="SelectedEntity"
RelativeSource="{RelativeSource Mode=FindAncestor,
AncestorType=Window}"
Mode="TwoWay"
NotifyOnValidationError="True"
NotifyOnTargetUpdated="True"
NotifyOnSourceUpdated="True"
ValidatesOnExceptions="True"
ValidatesOnDataErrors="True"
UpdateSourceTrigger="Default"
>
<Binding.ValidationRules>
<my:NonNullValidator ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</ComboBox.SelectedValue>
</ComboBox>
<Button Content="Select a null value." Click="Button_Click" Margin="5"/>
</StackPanel>
public partial class Window1 : Window,INotifyPropertyChanged
{
private int? myVar;
public int? SelectedEntity
{
get { return myVar; }
set { myVar = value; OnPropChanged("SelectedEntity"); }
}
public Window1()
{
InitializeComponent();
myEntityComboBox.ItemsSource = new[]
{
new { myEntityId = (int?)null, myEntityName="Null Option"},
new { myEntityId = (int?)1, myEntityName="#1"},
new { myEntityId = (int?)2, myEntityName="#2"}
};
myEntityComboBox.SelectedIndex = 0;
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
private void myEntityComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void Button_Click(object sender, RoutedEventArgs e)
{
myEntityComboBox.SelectedIndex = 0;
}
}
public class NonNullValidator : ValidationRule
{
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
return value == null
? new ValidationResult(false, "Gruu!")
: new ValidationResult(true, null);
}
}
我将不谈大事,但我在窗体上有一个 ComboBox,它't/isn 表现不正常。为了尝试通过实验解决问题,我创建了一个测试 WPF 项目,并将所有相关代码添加到一个简单的 WPF Window.
在我的原始表单中,当 ComboBox 上的 SelectedValue
更改时,我可以根据需要执行 ValidationRule。但是,将代码复制并粘贴到这个新项目后,我可以编译并 运行 程序没有错误,但是我无法让验证程序执行?
可以肯定的是,我在整个代码中都设置了断点。我永远无法在我的 ValidationRule
中使用 Validate(...)
方法,而且我不明白为什么这不起作用。特别是因为这是一个直接复制和粘贴,只为明显的参考需求更新了一些最小的命名空间,这在我原来的应用程序中肯定有效。
以下是所有相关代码。随意复制、粘贴和 运行.
XAML
<Window Height="270"
Title="MainWindow"
Width="532"
x:Class="WPFDataGridApp13.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:my="clr-namespace:WPFDataGridApp13"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<Style TargetType="ComboBox">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>
</Style.Triggers>
</Style>
<ControlTemplate x:Key="validationTemplate">
<Grid>
<Border BorderThickness="1" BorderBrush="Red" >
<AdornedElementPlaceholder />
</Border>
</Grid>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<ComboBox x:Name="myEntityComboBox"
DisplayMemberPath="myEntityName" SelectedValuePath="myEntityId"
Validation.ErrorTemplate="{StaticResource validationTemplate}"
VerticalAlignment="Center" Margin="5">
<ComboBox.SelectedValue>
<Binding Path="myEntityId"
Mode="TwoWay"
NotifyOnValidationError="True"
NotifyOnTargetUpdated="True"
NotifyOnSourceUpdated="True"
ValidatesOnExceptions="True"
ValidatesOnDataErrors="True"
UpdateSourceTrigger="PropertyChanged">
<!--<Binding.ValidationRules>
<my:NonNullValidator/>
</Binding.ValidationRules>-->
</Binding>
</ComboBox.SelectedValue>
</ComboBox>
<Button Content="Select a null value." Click="Button_Click" Margin="5"/>
</StackPanel>
</Window>
Window 代码隐藏
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace WPFDataGridApp13
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
myEntityComboBox.SelectedIndex = 0;
myEntityComboBox.ItemsSource = new[]
{
new { myEntityId = (int?)null, myEntityName="Null Option"},
new { myEntityId = (int?)1, myEntityName="#1"},
new { myEntityId = (int?)2, myEntityName="#2"}
};
Binding b = BindingOperations.GetBinding(myEntityComboBox, ComboBox.SelectedValueProperty);
b.ValidationRules.Clear();
b.ValidationRules.Add(new WPFDataGridApp13.NonNullValidator());
}
private void myEntityComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void Button_Click(object sender, RoutedEventArgs e)
{
myEntityComboBox.SelectedIndex = 0;
}
}
public class NonNullValidator : ValidationRule
{
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
return value == null
? new ValidationResult(false, "Gruu!")
: new ValidationResult(true, null);
}
}
}
快速说明,我的 NotNullValidator
的 XAML 声明是我指定验证器的原始方法,也是我设置此 属性 的首选方法。
我已经将其注释掉并在我的代码隐藏文件中设置了验证器,但这也没有用。无论我尝试什么,我都无法在 NonNullValidator
class 上点击 Validate
方法。
怎么回事?
您的绑定有问题。参考下面的代码。您需要将您选择的组合值绑定到一些 属性.
<Window x:Class="IconicZip_Learning.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:IconicZip_Learning"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<Style TargetType="ComboBox">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>
</Style.Triggers>
</Style>
<ControlTemplate x:Key="validationTemplate">
<Grid>
<Border BorderThickness="1" BorderBrush="Red" >
<AdornedElementPlaceholder />
</Border>
</Grid>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<ComboBox x:Name="myEntityComboBox"
DisplayMemberPath="myEntityName" SelectedValuePath="myEntityId"
Validation.ErrorTemplate="{StaticResource validationTemplate}"
VerticalAlignment="Center" Margin="5">
<ComboBox.SelectedValue>
<Binding Path="SelectedEntity"
RelativeSource="{RelativeSource Mode=FindAncestor,
AncestorType=Window}"
Mode="TwoWay"
NotifyOnValidationError="True"
NotifyOnTargetUpdated="True"
NotifyOnSourceUpdated="True"
ValidatesOnExceptions="True"
ValidatesOnDataErrors="True"
UpdateSourceTrigger="Default"
>
<Binding.ValidationRules>
<my:NonNullValidator ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</ComboBox.SelectedValue>
</ComboBox>
<Button Content="Select a null value." Click="Button_Click" Margin="5"/>
</StackPanel>
public partial class Window1 : Window,INotifyPropertyChanged
{
private int? myVar;
public int? SelectedEntity
{
get { return myVar; }
set { myVar = value; OnPropChanged("SelectedEntity"); }
}
public Window1()
{
InitializeComponent();
myEntityComboBox.ItemsSource = new[]
{
new { myEntityId = (int?)null, myEntityName="Null Option"},
new { myEntityId = (int?)1, myEntityName="#1"},
new { myEntityId = (int?)2, myEntityName="#2"}
};
myEntityComboBox.SelectedIndex = 0;
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
private void myEntityComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void Button_Click(object sender, RoutedEventArgs e)
{
myEntityComboBox.SelectedIndex = 0;
}
}
public class NonNullValidator : ValidationRule
{
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
return value == null
? new ValidationResult(false, "Gruu!")
: new ValidationResult(true, null);
}
}