C# ValidationRules在值设置回有效值时未删除错误
导言 我已经创建了一个DecimalTextBoxC# ValidationRules在值设置回有效值时未删除错误,c#,wpf,xaml,user-controls,validationrules,C#,Wpf,Xaml,User Controls,Validationrules,导言 我已经创建了一个DecimalTextBoxUserControl,其中包含了我需要进行的一些十进制验证,因此我不需要每次都重新创建验证,只需使用UserControl。此验证具有需要绑定的属性,因此我创建了dependencProperties,以便可以根据进行绑定 问题 控件的验证行为异常。当我在文本框中键入错误值时,它显示为错误。但是,当我尝试更改代码中的值时,文本框中显示的值保持不变 以下是我执行的导致此错误的步骤(在本例中,1是无效值): 加载表单,默认值为0 在文本框中输入1
UserControl
,其中包含了我需要进行的一些十进制验证,因此我不需要每次都重新创建验证,只需使用UserControl
。此验证具有需要绑定的属性,因此我创建了dependencProperties
,以便可以根据进行绑定
问题 控件的验证行为异常。当我在
文本框中键入错误值时,它显示为错误。但是,当我尝试更改代码中的值时,文本框中显示的值保持不变
以下是我执行的导致此错误的步骤(在本例中,1是无效值):
加载表单,默认值为0
在文本框中输入1(由于验证结果不正确,文本框变为红色)
在代码中,我将绑定到文本框的属性设置为0
表单仍在红色文本框中显示1
代码示例
我准备了一个例子来演示这个问题,可以下载
我会在这里发布一些代码,如果你想要更多,请告诉我
验证TestControl的XAML
<UserControl x:Class="WPFTestProject.ValidationTestControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:v="clr-namespace:WPFTestProject"
x:Name="ValidationTest"
Height="50" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Text="Type 'Banana' here: "></TextBlock>
<TextBox MinWidth="100">
<TextBox.Text>
<Binding ElementName="ValidationTest" Path="Text" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay" ValidatesOnDataErrors="True" ValidatesOnExceptions="True">
<Binding.ValidationRules>
<v:NotBananaValidationRule>
<v:NotBananaValidationRule.NotWhatBinding>
<v:NotBananaBinding x:Name="NotBananaValidationBinding"></v:NotBananaBinding>
</v:NotBananaValidationRule.NotWhatBinding>
</v:NotBananaValidationRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<TextBlock Text=" (the text will give error when = 'Banana')"></TextBlock>
</StackPanel>
</Grid>
为绑定创建的ValidationRule和FrameWorkElement
public class NotBananaValidationRule:ValidationRule
{
private NotBananaBinding _notWhatBinding;
public NotBananaBinding NotWhatBinding
{
get { return _notWhatBinding; }
set { _notWhatBinding = value; }
}
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
string what = value.ToString();
if(what == _notWhatBinding.NotWhat||string.IsNullOrEmpty(what))
return new ValidationResult(false,
"Please enter a string that is not " + _notWhatBinding.NotWhat);
else
return new ValidationResult(true, null);
}
}
public class NotBananaBinding : FrameworkElement
{
public static readonly DependencyProperty NotWhatProperty = DependencyProperty.Register(
"NotWhat", typeof(string), typeof(NotBananaBinding), new UIPropertyMetadata());
public string NotWhat
{
get { return (string)GetValue(NotWhatProperty); }
set { SetValue(NotWhatProperty, value); }
}
public NotBananaBinding() { }
}
基本上,这段代码所做的是检查您是否键入了“Banana”,然后返回一个验证错误。该控件公开依赖项属性,因为我希望在使用该控件时能够绑定到它们。FrameworkElement
NotBananaBinding允许我创建依赖项属性(因为它是一个DependencyObject
),所以我可以为验证绑定内容。ValidationRule有一个NotBananaBinding属性,存储依赖项属性并在validate方法中使用它
我知道我的属性名有点糟糕,抱歉。问题是示例在显示错误方面做得很好。在我匆忙制作示例的过程中,我没有很好地命名变量。如果您发现代码糟糕,请下载示例
到目前为止我所了解的情况
基本上,这个问题似乎是由我没有实际更改值这一事实引起的
即使我在属性上调用OnPropertyChanged,因为值没有不同,它也不会尝试重新评估验证
很明显,我可以将该值更改为任意有效值,然后将其更改为我希望的值,这样就可以工作了,但我希望有某种方法可以手动获取调用验证,重新评估该值,然后进行更改,等等。来回更改它有点混乱
结论
我是否做错了什么(可能是因为我实现了Josh Smith帖子中的验证和绑定的方式)
这仅仅是一个c#bug,还是行为的本意?如果是,那么为什么
有什么优雅的方法可以解决它吗
u_u验证阻止设置文本
属性。在setter上放置一个断点,您将看到当您键入最后一个“a”时,它不会中断。如果您键入Bananan并单击Backspace并显示错误,则按下按钮,它将工作。验证确保您的属性中没有无效值。因此,我如果在出错时将其保存到数据库中,它不会保存无效值。发布代码确实有帮助-人们不想运行示例项目。尝试将问题减少到再现问题的尽可能少的代码。你永远不知道,你可能会自己解决问题。如果你在在其中键入另一个字符将重新计算验证规则,但我的问题是我无法在代码中将其设置为有效值。由于验证阻止绑定发生,我似乎无法在删除绑定时通过代码更改文本框中的值。我尝试将文本框的值设置回以前的值,但原因是属性的值已经是该值(因为验证不允许更改无效值)没有更改通知,文本框值也没有刷新。您是如何设置文本框上的文本以删除绑定的,因为我在文本框旁边放置了一个按钮,它是onclick事件。我将文本框的文本设置为Banan,并且更改值会不断触发setter。您下载了示例吗?这很好地解释了我的问题t、 我所做的是在文本框中键入Banana。然后按下按钮将文本更改回Banan,它不会更改,因为属性的值已经是Banan。由于它没有更改,文本框中显示的文本保持为Banana。当验证引发错误时,绑定会断开,因为文本框中的文本是displays Banana,但值是BananI下载的,否则我无法在文本框旁边放置按钮。设置文本框的值而不是属性的值。是的,但问题是在我的真实项目中,我使用MVVM,所以我无法访问文本框的值。该示例显示了我如何无法通过更改属性来通过代码完成此操作。在rEallity这是一个没有按钮的控件,我尝试使用控件绑定到的属性将文本设置回viewmodel中。文本框位于控件内部,因此我无法直接访问它。我想我可以公开一个方法将其更改回,但我不确定我是否喜欢这个想法。
public class NotBananaValidationRule:ValidationRule
{
private NotBananaBinding _notWhatBinding;
public NotBananaBinding NotWhatBinding
{
get { return _notWhatBinding; }
set { _notWhatBinding = value; }
}
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
string what = value.ToString();
if(what == _notWhatBinding.NotWhat||string.IsNullOrEmpty(what))
return new ValidationResult(false,
"Please enter a string that is not " + _notWhatBinding.NotWhat);
else
return new ValidationResult(true, null);
}
}
public class NotBananaBinding : FrameworkElement
{
public static readonly DependencyProperty NotWhatProperty = DependencyProperty.Register(
"NotWhat", typeof(string), typeof(NotBananaBinding), new UIPropertyMetadata());
public string NotWhat
{
get { return (string)GetValue(NotWhatProperty); }
set { SetValue(NotWhatProperty, value); }
}
public NotBananaBinding() { }
}