ようこそ。睡眠不足なプログラマのチラ裏です。

常識的に考えてErrorProviderを使いたいよね

VB.NETでもC#でもいいんだけど、.NET Framework2.0以降でWindows.Formsなアプリを作る場合、
入力検証を行うようなときは、ErrorProviderを使いたいよね!*1というお話は、
.NETで飯を食っている人にとっては割と常識ではないかと思っていたのだが、実際のところそうでもないらしい。
未だにMessageBoxでいちいちエラー内容を通知してくれちゃっているとか・・。
オペレータさん、ウザすぎて使いずらいんじゃないだろうかってゆー。


そこで、ErrorProviderを利用した超適当なTextBoxExのコードを上げておく。

using System.ComponentModel;
using System.Windows.Forms;

namespace ClassLibrary1
{
    public interface IValidateCheck
    {
        bool IsValidate(string value);
    }

    public partial class TextBoxEx : TextBox 
    {
        /// <summary>
        /// コンストラクタ
        /// </summary>
        public TextBoxEx() : base(){}
        
        /// <summary>
        /// IValidateCheckを取得または設定します。
        /// </summary>
        public IValidateCheck ValidateCheckItem { get; set; }

        /// <summary>
        /// エラーメッセージに使用するメッセージを取得または設定します。既定値は null です。
        /// </summary>
        [Category("Validation")]
        [DefaultValue(null)]
        [Description("エラーメッセージに使用するテキストを取得または設定します。既定値は null です。")]
        public string ErrorMessage{get;set;}

        /// <summary>
        /// エラーメッセージを表示するエラープロバイダーコントロールを取得または設定します。既定値は null です。
        /// </summary>
        [Category("Validation")]
        [DefaultValue(null)]
        [ImmutableObject(true)]
        [Description("エラーメッセージを表示するエラープロバイダーコントロールを取得または設定します。既定値は null です。")]
        public ErrorProvider ErrorProvider{get;set;}
 
        /// <summary>
        /// エラーメッセージ(nullの場合はエラーなし)を設定します。
        /// </summary>
        /// <param name="message">string エラーメッセージ文字列(エラーなしの場合はnull)</param>
        public void SetError(Control control, string message)
        {
            if (this.ErrorProvider != null)
            {
                this.ErrorProvider.SetError(control, message);
            }
        }
        
        /// <summary>
        /// 検証を実行します。
        /// </summary>
        /// <param name="control">検証を行うコントロール Control</param>
        /// <param name="value">検証する文字列 string</param>
        /// <returns>検証エラーが発生したか否か bool</returns>
        public bool DoValidating(Control control, string value)
        {
            this.SetError(control, null);
            if (!ValidateCheckItem.IsValidate(value))
            {
                this.SetError(control, this.ErrorMessage);
                return false;            
            }
            return true;
        }
        
        /// <summary>
        /// OnValidating
        /// </summary>
        /// <param name="e">CancelEventArgs </param>
        protected override void OnValidating(CancelEventArgs e)
        {
            if (!this.DoValidating(this, this.Text))
            {
                e.Cancel = true;
                return;
            }
            e.Cancel = false;
            base.OnValidating(e);
        }
    }
}

それを使う時のクライアント側の実装

using System.Windows.Forms;
using ClassLibrary1;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            this.textBoxEx1.ValidateCheckItem = new CheckTest();
            this.textBoxEx1.ErrorProvider = this.errorProvider1;
            this.textBoxEx1.ErrorProvider.BlinkStyle = ErrorBlinkStyle.AlwaysBlink; 
            this.textBoxEx1.ErrorMessage = "エラーです";
        }
    }

    public class CheckTest : IValidateCheck {

        #region IValidateCheck メンバ

        public bool IsValidate(string value)
        {
            if (value == "") return true;
            if (!(value == "テスト")) {
                return false;
            }
            return true;
        }

        #endregion
    }
}

非常に雑なコードですが、応用および拡張のイメージはわきやすいかと。
これからErrorProviderを利用しようと思っている人の参考になれば幸い。


真面目にやったら、わんくまのえむナウさん作成のコントロールに近い感じになるかと思われる。
本気を出したい!真面目にやりたい!という方は参考にしてみてはいかがでしょうか。
http://www.geocities.jp/mnow/cs2005_mnowcontrol1.html

*1:まあ、ケースバイケースっちゃーケースバイケースなんですが