0

現在、Entity Framework 5.0 と WinForms を使用しています。私がやりたいのは、POCO クラスの検証をセットアップして、それらをフォーム フィールドにデータバインドするときに、ErrorProvider を介して UI 検証エラーを表示することです。子クラスが呼び出すいくつかの単純な検証メソッドを使用して IDataErrorInfo インターフェイスを実装する基本「ValidationEntity」クラスをセットアップしました。ほとんどの場合、フィールドの長さ、範囲などの検証は正常に機能しているようで、ErrorProvider を介してユーザーにエラーを表示します。

ただし、「ValidateRequiredField」メソッドで問題が発生したようです。null 非許容の整数フィールドを持つクラスがあり、ユーザーがたまたまフォームでこの値を削除した場合、ErrorProvider はエンドユーザーにメッセージを表示しますが、メッセージは「入力文字列は認識された形式ではありませんでした」です。 . これは、整数フィールドにバインドされているフォームが空のテキストを整数に変換しようとしていて、値が POCO クラス プロパティに送信される前に変換エラーが発生しているためだと思います。私の質問は、これを解決するための最良のアプローチは何でしょうか?

フォーム内に TextBox コントロールの Validating メソッドを実装し、空/null エントリをキャッチし、エラー プロバイダに適切なエラー メッセージを設定する必要があると思います。ただし、クラスに空/null値を処理させ、POCOクラス内でエラーを設定してUIに伝播させる方法を望んでいました. もともと、カスタム TypeConverter (RequiredIntTypeConverter など) を作成することを考えていましたが、ValidationEntity クラスから継承しているため、エラーに追加する良い方法が思いつかなかったので、問題が発生しました。

以下は、ValidationEntity クラスのサンプルと、Company クラスのスニペットです。

ValidationEntity.cs

public class ValidationEntity : IDataErrorInfo
{
    private readonly Dictionary<string, List<string>> errors = new Dictionary<string, List<string>>();

    string IDataErrorInfo.Error
    {
        get { return string.Empty; }
    }

    string IDataErrorInfo.this[string propertyName]
    {
        get
        {
            return (!errors.ContainsKey(propertyName) ? null : String.Join(Environment.NewLine, errors[propertyName]));
        }
    }

    public void AddError(string propertyName, string error, bool isWarning)
    {
        if (!errors.ContainsKey(propertyName))
        {
            errors[propertyName] = new List<string>();
        }

        if (!errors[propertyName].Contains(error))
        {
            if (isWarning)
            {
                errors[propertyName].Add(error);
            }
            else
            {
                errors[propertyName].Insert(0, error);
            }
        }
    }

    public void RemoveError(string propertyName, string error)
    {
        if (errors.ContainsKey(propertyName) &&
            errors[propertyName].Contains(error))
        {
            errors[propertyName].Remove(error);
            if (errors[propertyName].Count == 0)
            {
                errors.Remove(propertyName);
            }
        }
    }

    public void ValidateFieldLength(string propertyName, string value, int maxLength)
    {
        string errorMessage = string.Format("Text entered exceeds max length of {0} characters", maxLength);

        if (value != null)
        {
            if (value.Length > maxLength)
            {
                if (!errors.ContainsKey(propertyName))
                {
                    AddError(propertyName, errorMessage, false);
                }
            }
            else
            {
                RemoveError(propertyName, errorMessage);
            }
        }
        else
        {
            RemoveError(propertyName, errorMessage);
        }
    }

    public void ValidateRequiredField(string propertyName, string value)
    {
        string errorMessage = string.Format("{0} is required.", propertyName);

        if (string.IsNullOrWhiteSpace(value))
        {
            AddError(propertyName, errorMessage, false);
        }
        else
        {
            RemoveError(propertyName, errorMessage);
        }
    }        
}

会社.cs

public class Company : ValidationEntity
{
   private int companyID;
   private string companyName;

   public int CompanyID 
   {
     get { return this.companyID; }
     set 
     {
       OnCompanyIdChanging(value.ToString());
       this.companyID = value;
     } 
   }
   public string CompanyName
   {
     get { return this.companyName; }
     set 
     {
       OnCompanyNameChanging(value);
       this.companyName = value; 
     }
   }

   private void OnCompanyIdChanging(string value)
   {
     ValidateRequiredField("CompanyID", value);
   }

   private void OnCompanyNameChanging(string value)
   {
     ValidateRequiredField("CompanyName", value);
     ValidateFieldLength("CompanyName", value, 30);
   }
}

ご協力いただきありがとうございます。

4

1 に答える 1

0

これについてさらに調査を行い、コード サンプルをテストした後、この特定の項目に対する解決策を見つけることができました。Null 非許容整数変換には、カスタム TypeConverter が必要でした。ここで情報を見つけることができ 、「必要な整数」をテストするための次の TypeConverter になりました。

public class RequiredIntConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        if (sourceType == typeof(string))
        {
            return true;
        }
        return base.CanConvertFrom(context, sourceType);
    }

    [System.Diagnostics.DebuggerNonUserCode]
    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
    {
        if (value == null || string.IsNullOrWhiteSpace(value.ToString()))
        {
            throw new ApplicationException("This field requires an integer value and cannot be blank.");
        }
        int result = 0;
        if (!int.TryParse(value.ToString(), out result))
        {
            throw new ApplicationException("The value could not be parsed as a valid integer data type.");
        }
        else
        {
            return result;
        }
    }
}

上記のリンクのコードを最初にテストしたとき、ApplicationException をスローしようとすると、デバッガーが壊れ続けました。これは私のコードのエラーだと思い、TypeConverter の使用方法について混乱しました。ただし、デバッガーがメソッドで中断するのを抑制する方法を説明する 次の投稿を見つけました。

この ApplicationException で中断する理由と、ErrorProvider が基になる例外を表示することをどのように認識しているかについては、まだ少しわかりません。誰かがこれに関する追加のリソースを教えてくれれば、大歓迎です。

すてきな一日を。

于 2013-01-24T17:07:04.210 に答える