【问题标题】:Is it possible to create generic ValidationRule classes?是否可以创建通用 ValidationRule 类?
【发布时间】:2013-07-09 19:57:29
【问题描述】:

我正在开发一个处理特定数据类型范围验证的 .NET 4.0 项目。例如,32 位 int 应该只介于 Int32.MinValueInt32.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...
    }
}

【问题讨论】:

  • 您可以在 XAML 中使用 x:Type 来指定您传递给规则的类型。
  • 您能否通过显示示例验证规则类和 XAML 调用示例来回答这个问题?
  • 您如何将小于 Int32.MinValue 的值分配给 Int32?您希望如何在“集合”中设置超出 Int32 范围的“值”?
  • @Blam 这只是一个例子。理想情况下,此类的用户可以指定他/她想要的任何范围,而不仅仅是那些。
  • @Blam 这应该很容易适用于任何数据类型。

标签: c# .net wpf validation


【解决方案1】:

我的错,实际上你不能使用 x:TypeArguments,因为它会引发 x:TypeArguments 在低于 2009 的 XAML 版本的对象元素中是不允许的,它仅对松散的 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();
    }
}

也看看这个: Using a Generic IValueConverter from XAML

@Blam 注释值得考虑,要检查的范围通常适用于整数或双精度数,对于其他类型,我想说你可以添加一个返回该对象有效性的布尔值并在对象本身。

对于您拥有 RangeAttribute 的号码,但它实际上并不是 WPF 验证基础架构的一部分。

您还有另一个验证选项:INotifyDataErrorInfo 验证在这种情况下发生在对象内部。

我在这里写了一个很长的答案:https://softwareengineering.stackexchange.com/questions/203590/is-there-an-effective-way-for-creating-complex-forms你可能会发现一些有用的东西。

根据我的经验,我认为通用的验证规则可能并不明智。

您应该编辑您的问题以减少通用 ;-) 而是更具体,您会从这里的人那里获得更多帮助。给出您要验证的对象的一两个具体案例。

编辑

您还可以使用 BindingGroup 来验证对象:

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>

使用 RangeAtribute :

    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; }
}

【讨论】:

  • 非常感谢。这很有帮助!
  • 欢迎来到 StackOverflow !
猜你喜欢
  • 1970-01-01
  • 2016-10-30
  • 2019-03-19
  • 1970-01-01
  • 2016-09-25
  • 2018-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多