【问题标题】:CustomValidation attribute doesn't seem to workCustomValidation 属性似乎不起作用
【发布时间】:2011-06-08 21:57:40
【问题描述】:

我的 Silverlight 4 应用程序中有一个简单的测试页面,我试图在其中触发自定义验证规则。

我有一个 TextBox 和一个 Button,我在 TextBlock 中显示验证结果。我的视图模型有一个 Name 属性,它绑定了 TextBox 的 Text 属性。我在 Name 属性上有两个验证属性,[Required][CustomValidation]

当我点击提交按钮时,Required 验证器会正确触发,但我的自定义验证器的验证方法内的断点永远不会被命中。我不明白为什么会这样,因为我认为我非常仔细地遵循了 MS 的示例:http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.customvalidationattribute(v=vs.95).aspx

这是视图模型的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using GalaSoft.MvvmLight.Command;

namespace MyProject
{
    // custom validation class
    public class StartsCapitalValidator
    {
        public static ValidationResult IsValid(string value)
        {
            // this code never gets hit
            if (value.Length > 0)
            {
                var valid = (value[0].ToString() == value[0].ToString().ToUpper());
                if (!valid)
                    return new ValidationResult("Name must start with capital letter");
            }
            return ValidationResult.Success;
        }
    }

    // my view model
    public class ValidationTestViewModel : ViewModelBase
    {
        // the property to be validated
        string _name;
        [Required]
        [CustomValidation(typeof(StartsCapitalValidator), "IsValid")]
        public string Name
        {
            get { return _name; }
            set { SetProperty(ref _name, value, () => Name); }
        }

        string _result;
        public string Result
        {
            get { return _result; }
            private set { SetProperty(ref _result, value, () => Result); }
        }

        public RelayCommand SubmitCommand { get; private set; }

        public ValidationTestViewModel()
        {
            SubmitCommand = new RelayCommand(Submit);
        }

        void Submit()
        {
            // perform validation when the user clicks the Submit button
            var errors = new List<ValidationResult>();
            if (!Validator.TryValidateObject(this, new ValidationContext(this, null, null), errors))
            {
                // we only ever get here from the Required validation, never from the CustomValidator
                Result = String.Format("{0} error(s):\n{1}",
                    errors.Count,
                    String.Join("\n", errors.Select(e => e.ErrorMessage)));
            }
            else
            {
                Result = "Valid";
            }
        }
    }
}

这是视图:

<navigation:Page x:Class="Data.Byldr.Application.Views.ValidationTest" 
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
           xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
           xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
           xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation">
    <Grid Width="400">
    <StackPanel>
        <TextBox Text="{Binding Name, Mode=TwoWay}" />
        <Button Command="{Binding SubmitCommand}" Content="Submit" />
        <TextBlock Text="{Binding Result}" />
    </StackPanel>
    </Grid>
</navigation:Page>

【问题讨论】:

标签: c# silverlight validation mvvm data-annotations


【解决方案1】:

你为什么不像这样创建自己的 Validation 属性..

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

public class StartsCapital : ValidationAttribute 
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var text = value as string;

            if(text == null)
                return ValidationResult.Success;

            if (text.Length > 0)
            {
                var valid = (text[0].ToString() == text[0].ToString().ToUpper());
                if (!valid)
                    return new ValidationResult("Name must start with capital letter");
            }
            return ValidationResult.Success;
        }
}

然后像这样使用它

 // my view model
public class ValidationTestViewModel : ViewModelBase
{
    // the property to be validated
    string _name;
    [Required]
    [StartsCapital]
    public string Name
    {
        get { return _name; }
        set { SetProperty(ref _name, value, () => Name); }
    }

【讨论】:

  • 我更喜欢这个而不是 [CustomValidation] 属性。
【解决方案2】:

正如 MSDN 页面上针对 Validator.TryValidateObject ( http://msdn.microsoft.com/en-us/library/dd411803(v=VS.95).aspx ) 的重载所述,仅使用此方法检查对象级验证,并在属性上检查 RequiredAttribute。

要检查属性级验证,请使用也接受布尔值 (http://msdn.microsoft.com/en-us/library/dd411772(v=VS.95).aspx) 的重载

所以它应该像将“true”作为额外参数传递给TryValidateObject一样简单

【讨论】:

猜你喜欢
  • 2010-10-08
  • 1970-01-01
  • 2010-11-16
  • 2010-12-08
  • 2013-07-31
  • 1970-01-01
  • 2015-10-05
  • 2014-02-24
  • 2021-09-12
相关资源
最近更新 更多