34


23

WPFとEntity FrameworkでDataAnnotationsを使用してデータを検証しますか?

WPFとEntity FrameworkでDataAnnotationsを使用して検証する方法はありますか?

7 Answer


45


ここで説明するように、DataAnnotations.Validatorクラスを使用できます。

ただし、メタデータに「バディ」クラスを使用している場合、ここで説明するように、検証する前にその事実を登録する必要があります。

TypeDescriptor.AddProviderTransparent(
  new AssociatedMetadataTypeTypeDescriptionProvider(typeof(myEntity),
    typeof(myEntityMetadataClass)),
  typeof(myEntity));

List results = new List();
ValidationContext context = new ValidationContext(myEntity, null, null)
bool valid = Validator.TryValidateObject(myEntity, context, results, true);
  • [シミーのコメントに応答するために以下を追加] *

上記のロジックを実装するためのジェネリックメソッドを作成し、どのオブジェクトでも呼び出せるようにしました。

// If the class to be validated does not have a separate metadata class, pass
// the same type for both typeparams.
public static bool IsValid(this T obj, ref Dictionary errors)
{
    //If metadata class type has been passed in that's different from the class to be validated, register the association
    if (typeof(T) != typeof(U))
    {
        TypeDescriptor.AddProviderTransparent(new AssociatedMetadataTypeTypeDescriptionProvider(typeof(T), typeof(U)), typeof(T));
    }

    var validationContext = new ValidationContext(obj, null, null);
    var validationResults = new List();
    Validator.TryValidateObject(obj, validationContext, validationResults, true);

    if (validationResults.Count > 0 && errors == null)
        errors = new Dictionary(validationResults.Count);

    foreach (var validationResult in validationResults)
    {
        errors.Add(validationResult.MemberNames.First(), validationResult.ErrorMessage);
    }

    if (validationResults.Count > 0)
        return false;
    else
        return true;
}

検証する必要がある各オブジェクトに、このメソッドへの呼び出しを追加します。

[MetadataType(typeof(Employee.Metadata))]
public partial class Employee
{
    private sealed class Metadata
    {
        [DisplayName("Email")]
        [Email(ErrorMessage = "Please enter a valid email address.")]
        public string EmailAddress { get; set; }
    }

    public bool IsValid(ref Dictionary errors)
    {
        return this.IsValid(ref errors);
        //If the Employee class didn't have a buddy class,
        //I'd just pass Employee twice:
        //return this.IsValid(ref errors);
    }
}


4


クレイグスの答えに欠けているのは、検証エラーがあるかどうかを実際に確認する方法だと思います。 これは、Steve Sandersonによって書かれた、Deferent Layerで検証チェックを実行したい人のために書かれたDataAnnotation検証ランナーです。プレゼンテーション(http://blog.codeville.net/category/xval/、コードはサンプルプロジェクトです)

public static IEnumerable GetErrors(object instance)
{
    var metadataAttrib = instance.GetType().GetCustomAttributes
        (typeof(MetadataTypeAttribute), true).
            OfType().FirstOrDefault();
    var buddyClassOrModelClass =
        metadataAttrib != null ?
        metadataAttrib.MetadataClassType :
        instance.GetType();
    var buddyClassProperties = TypeDescriptor.GetProperties
        (buddyClassOrModelClass).Cast();
    var modelClassProperties = TypeDescriptor.GetProperties
        (instance.GetType()).Cast();

    return from buddyProp in buddyClassProperties
           join modelProp in modelClassProperties
               on buddyProp.Name equals modelProp.Name
           from attribute in buddyProp.Attributes.
               OfType()
           where !attribute.IsValid(modelProp.GetValue(instance))
           select new ErrorInfo(buddyProp.Name,
               attribute.FormatErrorMessage(string.Empty), instance);
}

私はWPFに精通していません(あなたの質問にすぐに使えるソリューションがあるかどうかはわかりません)が、おそらくあなたはそれを使うことができます。

また、彼のブログには、検証ルールを適切に評価できない場合がありますが、決して失敗しなかったというコメントがあります。


3


  • http://waf.codeplex.com [WPF Application Framework(WAF)] BookLibrary *サンプルアプリケーションに興味があるかもしれません。 WPF&Entity FrameworkでDataAnnotationsを使用して、まさに求めていることを行います。


1


同じ質問があり、次のアイデアを見つけました。


0


「バディクラス」を使用します。 this how-toの4番目。


0


NET 4では、この拡張機能を使用したEntity-Frameworkの検証サポートがあります。http://blogs.msdn.com/adonet/archive/2010/01/13/introducing-the-portable-extensible-metadataを確認してください。 aspx

DataAnnotations thoを使用しているかどうかはわかりません。

  • UPDATE * + VB.NETで試してみたが機能しなかった。C#プロジェクトのみをサポートしていると思う。


0


DataAnnotation検証コントリビューターを含むコントリビューターベースのバリデーターを作成し、破損したバインディング(ユーザーが間違ったタイプを入力した場合)をチェックします