7

ViewModel で を使用して入力を検証するapplication WPF( .Net 3.5) があります。IDataErrorInfo

それはうまく機能し、ユーザーコントロールは正しいUIフィードバックを取得します。

問題は、ユーザーが選択した要素を変更したり、この要素を保存したりできることです。

私の質問は次のとおりです。すべてのプロパティが有効であることをどのように知ることができますか? または、少なくとも表示されたすべての値が有効であること。IsActive目標は、この結果にいくつかをバインドすることです

4

3 に答える 3

17

実装に関するコメントから、IDataErrorInfo実装をこのスタイルに変更してください....

#region IDataErrorInfo Members

public string Error
{
    get { return this[null] }
}

public string this[string columnName]
{
    get
    {
        StringBuilder result = new StringBuilder();
        if (string.IsNullOrEmpty(columnName) || columnName == "FirstName")
        {
            if (string.IsNullOrEmpty(FirstName))
                result.Append("Please enter a First Name\n");
        }
        if (string.IsNullOrEmpty(columnName) || columnName == "LastName")
        {
            if (string.IsNullOrEmpty(LastName))
                result.Append("Please enter a Last Name\n");
        }
       if (string.IsNullOrEmpty(columnName) || columnName == "Age")
        {
            if (Age < = 0 || Age >= 99)
                result.Append("Please enter a valid age\n");
        }
        return (result.Length==0) ? null : result.Remove(result.Length-1,1).ToString();
    }
}

#endregion


public bool IsValid {
   get { return string.IsNullOrEmpty(this.Error); }
}

次に、プロパティ変更イベントで

if (e.PropertyName == "Error") {
   OnPropertyChanged(this,new PropertyChangedEventArgs("IsValid"));
}
if (e.PropertyName != "Error" && e.PropertyName != "IsValid") {
   OnPropertyChanged(this,new PropertyChangedEventArgs("Error"));
}
于 2012-11-28T14:43:49.740 に答える
0

とりあえず、このメソッドをモデルに追加しました。

    public Boolean IsModelValid()
    {
        Boolean isValid = true;
        PropertyInfo[] properties = GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

        foreach (PropertyInfo p in properties)
        {
            if (!p.CanWrite || !p.CanRead)
            {
                continue;
            }
            if (this[p.Name] != null)
            {
                isValid = false;
            }
        }
        return isValid;
    }

オブジェクト自体を PropertyChanged イベントにバインドしました。

    public MyClassName()
    {
        PropertyChanged += CheckModelValidity;
        CheckModelValidity(null, null);
    }

変更されたときにこのメソッドを呼び出し、結果が実際のパブリック メンバーと異なる場合は更新します。

    private void CheckModelValidity(object sender, PropertyChangedEventArgs e)
    {
        bool isModelValid = IsModelValid();
        if(isModelValid!= IsValid)
        {
            IsValid = isModelValid;
        }
    }

そして、IsValid プロパティをバインドするだけです。

より良い解決策があるかどうかわかりませんか?

于 2012-11-28T12:24:25.787 に答える
0

アイデアをくれたBob Valeに感謝します!いくつかのモデルがあり、コードが非常に反復的であることに気付きました。この基本クラスを作成しました:

using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;

namespace Core.Models
{
    public abstract class ValidatableObject : IDataErrorInfo
    {
        public virtual bool IsValid() => this[null] == null;

        [NotMapped]
        public string? Error => this[null];

        [NotMapped]
        protected abstract (string, Func<string?>)[] Checks { get; }

        public virtual string? this[string? name] => validate(name, Checks);

        private static string? validate(string? name, params (string, Func<string?>)[] checks)
        {
            StringBuilder results = new();

            foreach ((string val, Func<string?> check) in checks)
            {
                if (String.IsNullOrEmpty(name) || name == val)
                {
                    string? result = check();
                    if (result != null)
                        results.AppendLine(result);
                }
            }

            return results.Length == 0
                ? null
                : results.ToString(0, results.Length - Environment.NewLine.Length);
        }
    }
}

そして、ここに使用法があります:

    private class Validatable : ValidatableObject
    {
        public string Email { get; set; }
        public string Comment { get; set; }

        protected override (string, Func<string?>)[] Checks => new (string, Func<string?>)[]
        {
            (nameof(Email), () => Validate.Email(Email)),
            (nameof(Comment), () => Validate.LengthOfOptionalString(Comment)),
        };
    }
于 2021-07-23T18:58:57.363 に答える