13

私は、WPF Validation および に関する多くのブログ投稿を読みましたDataAnnotations。私のエンティティDataAnnotationsと同じように使用するクリーンな方法があるかどうか疑問に思っていました。ValidationRules

したがって、これ( Source )の代わりに:

<Binding Path="Age" Source="{StaticResource ods}" ... >
  <Binding.ValidationRules>
    <c:AgeRangeRule Min="21" Max="130"/>
  </Binding.ValidationRules>
</Binding>

あなたが持っていなければならない場所

public class AgeRangeRule : ValidationRule 
{...}

WPF Binding で Age プロパティを確認し、次のように DataAnnotation を探します。

[Range(1, 120)]
public int Age
{
  get { return _age; }
  set
  {
    _age = value;
    RaisePropertyChanged<...>(x => x.Age);
  }
}

これが可能であれば何か考えはありますか?

4

5 に答える 5

8

私が見つけた最も近いアプローチは次のとおりです。

// This loop into all DataAnnotations and return all errors strings
protected string ValidateProperty(object value, string propertyName)
{
  var info = this.GetType().GetProperty(propertyName);
  IEnumerable<string> errorInfos =
        (from va in info.GetCustomAttributes(true).OfType<ValidationAttribute>()
         where !va.IsValid(value)
         select va.FormatErrorMessage(string.Empty)).ToList();


  if (errorInfos.Count() > 0)
  {
    return errorInfos.FirstOrDefault<string>();
  }
  return null;

ソース

public class PersonEntity : IDataErrorInfo
{

    [StringLength(50, MinimumLength = 1, ErrorMessage = "Error Msg.")]
    public string Name
    {
      get { return _name; }
      set
      {
        _name = value;
        PropertyChanged("Name");
      }
    }

public string this[string propertyName]
    {
      get
      {
        if (porpertyName == "Name")
        return ValidateProperty(this.Name, propertyName);
      }
    }
}

ソースソース

そうすれば、DataAnnotation は正常に動作し、XAML で最低限の作業を行うことがValidatesOnDataErrors="True"できます。これは、DataAnnotation を使用した Aaron の投稿の優れた回避策です。

于 2011-02-07T19:48:04.563 に答える
5

あなたのモデルIDataErrorInfoでは、このようなことを実装して行うことができます...

string IDataErrorInfo.this[string columnName]
{
    get
    {
        if (columnName == "Age")
        {
            if (Age < 0 ||
                Age > 120)
            {
                return "You must be between 1 - 120";
            }
        }
        return null;
    }
}

また、新しく定義された動作をバインド ターゲットに通知する必要があります。

<TextBox Text="{Binding Age, ValidatesOnDataErrors=True}" />

編集

データ注釈のみを使用する場合は、このブログ投稿に従ってタスクを実行する方法を概説します。

更新

前述のリンクの歴史的表現。

于 2011-02-04T21:24:21.947 に答える
0

アーロンいいですね。私はWPFに夢中で、来週職場でデータバインディングを研究します;)だからあなたの答えを完全に判断することはできません...

しかし、winforms では、Entlib の Validation Application Blockを使用し、ベース エンティティ (ビジネス オブジェクト) にIDataErrorInfo (実際には、DevExpress コントロールを使用しているため、IDXDataErrorInfo) を実装しました。

この方法でスケッチしたソリューションよりも少し洗練されたものであり、検証ロジックをインターフェイスの実装ではなくオブジェクトに配置します。より OOP で保守しやすいものにします。ID(XD)ataErrorInfo で、Validation.Validate(this) を呼び出すか、インターフェースが呼び出されたプロパティのバリデーターを取得して、特定のバリデーターを検証します。プロパティの組み合わせの検証のため、[SelfValidation] も呼び出すことを忘れないでください ;)

于 2011-02-04T21:48:04.270 に答える
0

最近、Data Annotation API を使用して WPF の EF Code First POCO クラスを検証するという同じ考えを思いつきました。Philippe の投稿のように、私のソリューションはリフレクションを使用していますが、必要なコードはすべて汎用バリデーターに含まれています。

internal class ClientValidationRule : GenericValidationRule<Client> { }

internal class GenericValidationRule<T> : ValidationRule
{
  public override ValidationResult Validate(object value, CultureInfo cultureInfo)
  {
    string result = "";
    BindingGroup bindingGroup = (BindingGroup)value;
    foreach (var item in bindingGroup.Items.OfType<T>()) {
      Type type = typeof(T);
      foreach (var pi in type.GetProperties()) {
        foreach (var attrib in pi.GetCustomAttributes(false)) {
          if (attrib is System.ComponentModel.DataAnnotations.ValidationAttribute) {
            var validationAttribute = attrib as System.ComponentModel.DataAnnotations.ValidationAttribute;
            var val = bindingGroup.GetValue(item, pi.Name);
            if (!validationAttribute.IsValid(val)) { 
              if (result != "")
                result += Environment.NewLine;
              if (string.IsNullOrEmpty(validationAttribute.ErrorMessage))
                result += string.Format("Validation on {0} failed!", pi.Name);
              else
                result += validationAttribute.ErrorMessage;
            }
          }
        }
      }
    }
    if (result != "")
      return new ValidationResult(false, result);
    else 
      return ValidationResult.ValidResult;
  }
}

上記のコードは、ジェネリック GenericValidationRule クラスから派生した ClientValidatorRule を示しています。Client クラスは、検証される私の POCO クラスです。

public class Client {
    public Client() {
      this.ID = Guid.NewGuid();
    }

    [Key, ScaffoldColumn(false)]
    public Guid ID { get; set; }

    [Display(Name = "Name")]
    [Required(ErrorMessage = "You have to provide a name.")]
    public string Name { get; set; }
}
于 2013-12-12T21:56:59.087 に答える
0

WPF アプリケーション フレームワーク (WAF)のBookLibraryサンプル アプリケーションに興味があるかもしれません。DataAnnotations Validation 属性を WPF Binding と共に使用します。

于 2011-02-05T15:27:34.253 に答える