C# 基于WPF中现有数据的验证
我需要创建一个验证节点,如果输入的值已经存在,该节点将返回一个错误。我有GUI,其中的项目可以设置名称。我想强制这些名称是唯一的 因此,对于每个验证,我需要以下两个参数:C# 基于WPF中现有数据的验证,c#,wpf,data-binding,validationrule,C#,Wpf,Data Binding,Validationrule,我需要创建一个验证节点,如果输入的值已经存在,该节点将返回一个错误。我有GUI,其中的项目可以设置名称。我想强制这些名称是唯一的 因此,对于每个验证,我需要以下两个参数: 所有项的所有名称的列表,或者一些谓词,它们将告诉我一个名称存在 当前项名称,将其从上述验证中排除(将名称更改为相同的值不应是错误) 数据上下文如下所示(仅用于说明的界面): 我尝试使用下面的答案进行正确绑定,但随后出现错误: 无法在类型为MyProject\u Validation\u UniqueNameRule\u 9
- 所有项的所有名称的列表,或者一些谓词,它们将告诉我一个名称存在
- 当前项名称,将其从上述验证中排除(将名称更改为相同的值不应是错误)
MyProject\u Validation\u UniqueNameRule\u 9\u 468654的“MyName”属性上设置“Binding”。只能对DependencyObject的DependencyProperty设置“绑定”
看起来根本不支持绑定
那么,我该如何将这两个变量放在一起,以便验证规则可以访问这两个变量呢?由于验证规则如何落在可视化树上的性质,绑定正在失败,这可能是您所怀疑的
绑定上还有其他风格的(请参阅该文档中的属性部分)
最终需要父节点,这里有一个用于可能相关的样式:
<vmvalidation:UniqueNameRule
MyName="{Binding Name, RelativeSource={RelativeSource TemplatedParent}}"/>
由于验证规则如何落在可视化树上的性质,绑定失败,这可能是您所怀疑的
绑定上还有其他风格的(请参阅该文档中的属性部分)
最终需要父节点,这里有一个用于可能相关的样式:
<vmvalidation:UniqueNameRule
MyName="{Binding Name, RelativeSource={RelativeSource TemplatedParent}}"/>
绑定可能是正确的,但我得到了这个错误:“不能在类型为MyProject\u Validation\u UniqueNameRule\u 9\u 468654
的'MyName'属性上设置'binding'。只能在DependencyObject的DependencyProperty上设置'binding'。所以我猜绑定不是这里的解决方案。我能做什么?在阅读您的评论时,它提醒我一个绑定问题,该问题也有类似的失败,但必须使用TwoWay
binding来解决。。。。也许你可以创建一个小的测试项目来演示这个问题,并在这里提供给我们尝试。如果创建它还需要其他任何东西的话,那么它可能会揭示为什么这个绑定不同于其他类型的绑定。我现在很好奇这是否是最简单的方法。绑定可能是正确的,但我得到了这个错误:“不能在类型为MyProject\u Validation\u UniqueNameRule\u 9\u 468654
的'MyName'属性上设置'binding'。只能在DependencyObject的DependencyProperty上设置'binding'所以我猜绑定不是这里的解决方案。我能做什么?在阅读您的评论时,它提醒我一个绑定问题,该问题也有类似的失败,但必须使用TwoWay
binding来解决。。。。也许你可以创建一个小的测试项目来演示这个问题,并在这里提供给我们尝试。如果创建它还需要其他任何东西的话,那么它可能会揭示为什么这个绑定不同于其他类型的绑定。我只是好奇这是不是最简单的方法。
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows.Controls;
namespace MyApp.Validation
{
public class UniqueNameRule : ValidationRule
{
public IEnumerable<string> ExistingNames { get; set; }
public string MyName { get; set; }
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
if(value is string newValue)
{
// name changed
if(!value.Equals(MyName))
{
if(ExistingNames.Contains(newValue))
{
return new ValidationResult(false, "Name already exists!");
}
}
return new ValidationResult(true, null);
}
else
{
return new ValidationResult(false, "Invalid value type. Is this validator valid for the given field?");
}
}
}
}
<Binding.ValidationRules>
<vmvalidation:UniqueNameRule MyName="{Binding Name}" />
</Binding.ValidationRules>
{Binding Path=DataContext.ItemNames, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}
<vmvalidation:UniqueNameRule
MyName="{Binding Name, RelativeSource={RelativeSource TemplatedParent}}"/>
<vmvalidation:UniqueNameRule
MyName="{Binding Name, RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type TextBox}}"/>