[英]Is it possible to create generic ValidationRule classes?
我正在处理一个 .NET 4.0 项目,该项目处理特定数据类型范围的验证。 例如,32 位 int 应该仅介于Int32.MinValue
和Int32.MaxValue
之间或应用程序定义的任何其他值。 我希望能够在自定义验证器上指定数据类型和范围,以便可以通过绑定直接从 xaml 调用它们: <CheckIfValueRangeValidator>
这就是我的想法,我不确定它是否有效,或者是否可以通过 xaml 完成。
class CheckIfValueInRangeValidator<T> : ValidationRule
{
public T Max { get; set; }
public T Min { get; set; }
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
// Implementation...
}
}
我的不好,实际上你不能使用 x:TypeArguments 因为它会引发x:TypeArguments is not allowed in object elements for XAML version lower than 2009 ,它只对松散的 XAML 文件或根元素有效(在我的例子中是窗口)......
http://msdn.microsoft.com/en-us/library/ms750476.aspx
但作为一种解决方法,您可以使用以下模式:
<TextBox x:Name="textBox1">
<Binding Path="MyValue"
Source="{StaticResource MyObject}"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<wpfApplication6:MyValidationRule ObjectType="{x:Type system:Int32}" />
</Binding.ValidationRules>
</Binding>
</TextBox>
代码背后:
public class MyObject
{
public object MyValue { get; set; }
}
public class MyValidationRule : ValidationRule
{
public Type ObjectType { get; set; }
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
throw new NotImplementedException();
}
}
也看看这个: 使用来自 XAML 的通用 IValueConverter
@Blam 评论值得考虑,要检查的范围通常适用于 integer 或双精度,对于其他类型,我会说您可以添加一个 boolean,它返回 object 的有效性,并在 object 本身内执行此类验证。
对于数字,您有RangeAttribute但它实际上并不是 WPF 验证基础结构的一部分。
您还有另一个验证选项:在这种情况下, INotifyDataErrorInfo验证发生在 object 内部。
我在这里写了一个冗长的答案: https://softwareengineering.stackexchange.com/questions/203590/is-there-an-effective-way-for-creating-complex-forms你可能会在上面找到有用的东西。
根据我的经验,我会说通用验证规则可能并不明智。
您应该将您的问题编辑得不那么笼统;-) 而是更具体一些,您会从这里的人那里得到更多帮助。 给出你试图验证的对象的一两个具体案例。
编辑
您还可以使用 BindingGroup 来验证 object:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void TextBox1_OnTextChanged(object sender, TextChangedEventArgs e)
{
grid.BindingGroup.CommitEdit();
}
}
public class Indices
{
public int ColorIndex { get; set; }
public string ColorPrefix { get; set; }
public int GradientIndex { get; set; }
public string GradientPrefix { get; set; }
}
public class ValidateMe : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
var bindingGroup = value as BindingGroup;
var o = bindingGroup.Items[0] as Indices;
return new ValidationResult(true, null);
}
}
<Window x:Class="WpfApplication6.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfApplication6="clr-namespace:WpfApplication6"
Title="MainWindow"
Width="525"
Height="350">
<Window.Resources>
<wpfApplication6:Indices x:Key="Indices"
ColorIndex="1"
ColorPrefix="MyColor"
GradientIndex="1"
GradientPrefix="MyGradient" />
</Window.Resources>
<Grid x:Name="grid" DataContext="{StaticResource Indices}">
<Grid.BindingGroup>
<BindingGroup>
<BindingGroup.ValidationRules>
<wpfApplication6:ValidateMe />
</BindingGroup.ValidationRules>
</BindingGroup>
</Grid.BindingGroup>
<TextBox TextChanged="TextBox1_OnTextChanged">
<Binding Path="ColorIndex" UpdateSourceTrigger="PropertyChanged" />
</TextBox>
</Grid>
</Window>
使用范围属性:
private void test()
{
Indices indices = new Indices();
indices.ColorIndex = 20;
var validationContext = new ValidationContext(indices);
var validationResults = new List<System.ComponentModel.DataAnnotations.ValidationResult>();
var tryValidateObject = Validator.TryValidateObject(indices, validationContext, validationResults,true);
}
public class Indices
{
[Range(1, 10)]
public int ColorIndex { get; set; }
public string ColorPrefix { get; set; }
public int GradientIndex { get; set; }
public string GradientPrefix { get; set; }
}
我有一个类似的问题:我需要一个特定于绑定源的ValidationRule
,即我希望源定义规则。
我最终使用了以下设置绑定的附加属性的方法,包括。 通过代码规则。
ICustomRuleProvider.cs :绑定源 (ViewModel) 必须实现的接口。
public interface ICustomRuleProvider
{
ValidationRule CreateRule();
}
CustomRule.cs :Xaml 中用于创建所需绑定的附加属性,包括。 规则。
public class CustomRule
{
public static ICustomRuleProvider GetProvider(DependencyObject obj)
{
return (ICustomRuleProvider)obj.GetValue(ProviderProperty);
}
public static void SetProvider(DependencyObject obj, ICustomRuleProvider value)
{
obj.SetValue(ProviderProperty, value);
}
public static readonly DependencyProperty ProviderProperty =
DependencyProperty.RegisterAttached("Provider", typeof(ICustomRuleProvider), typeof(CustomRule), new FrameworkPropertyMetadata(null, CustomRule.OnProviderPropertyChanged));
public static void OnProviderPropertyChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (!(sender is TextBox fe)) return;
var provider = e.NewValue as ICustomRuleProvider;
if (provider != null)
{
var b = new Binding("Value");
b.ValidationRules.Add(provider.CreateRule());
fe.SetBinding(System.Windows.Controls.TextBox.TextProperty, b);
}
else
{
BindingOperations.ClearBinding(fe, TextBox.TextProperty);
}
}
}
示例:务必定义xmlns:customRule="clr-namespace:...;assembly=..."
<TextBox customRule:CustomRule.Provider="{Binding}"/>
此实现是为将TextBox
的Text
属性绑定到绑定源的“Value”属性而量身定制的,但这可以轻松扩展。
使用它我能够使用自定义(通用)转换器。
顺便说一句:我不同意自定义通用ValidationRule
是一个“坏主意”,尽管用例可能有限。 在许多情况下,可能还需要实现自定义IValueConverter
并将其分配给绑定,以便在从控件到源的过程中完全控制 object 值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.