- PR -

ボタンのショートカットとValidatingの動作

投稿者投稿内容
SADAS
会議室デビュー日: 2007/01/17
投稿数: 4
投稿日時: 2007-01-17 13:49
お世話になっています。初めて投稿します。
.NET2003 C#を使っています。

<実現したいこと>
○コントロール
・テキストボックスとボタンを配置します。
・ボタンにはショートカットを設定しています。(&P)
○動き
テキストボックスに値を入力し、ボタン押下時(クリックでもショートカットでも)に入力チェックを行いNGであればテキストボックスに戻る。

<現在のコード>
private void button1_Click(object sender, System.EventArgs e)
{
  Console.WriteLine("{0}","button1_Click");
  button1.Select();
}

private void textBox1_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
  Console.WriteLine("{0}:{1}","textBox1_Validating",ActiveControl.Name);

  if(ActiveControl.Equals(sender)) return; //--------@
  //検証する条件
  if(textBox1.Text == "ERR")
  {
    e.Cancel = true;
  }
}

<事象>
ボタンをクリックした時はうまく動くのですが、検証がエラーになる値をテキストに入力し、ショートカットでボタンを連続押下した時、想定した動きになりません。

ショートカットで押下1回目は以下のようになります。
 textBox1_Validating:textBox1
 button1_Click
 textBox1_Validating:button1
ショートカットで押下2回目以降は以下のようになります。
 textBox1_Validating:textBox1 ----2回目
 textBox1_Validating:textBox1 ----3回目
 textBox1_Validating:textBox1 ----4回目

2回目以降、ショートカットでボタンを押下してもテキストボックスのValidatingしか走らず、button1_Clickメソッドが実行されない為、検証ができない状態となり困っています。
@の条件は「×」押下時等で必要なので外せません。


なにか良い方法があればご教授願います。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-01-17 15:06
引用:

SADASさんの書き込み (2007-01-17 13:49) より:

ショートカットで押下2回目以降は以下のようになります。
 textBox1_Validating:textBox1 ----2回目
 textBox1_Validating:textBox1 ----3回目
 textBox1_Validating:textBox1 ----4回目


これは、単純に button1 にフォーカスが移っているからではないでしょうか。

それと、Validating で検証中にフォーカスを動かすことはしない方が良いです。
予期しないことが起きます。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
SADAS
会議室デビュー日: 2007/01/17
投稿数: 4
投稿日時: 2007-01-17 16:30
引用:

じゃんぬねっとさんの書き込み (2007-01-17 15:06) より:

これは、単純に button1 にフォーカスが移っているからではないでしょうか。



textBox1_ValidatingのConsole.WriteLineを以下に変更して試してみました。

Console.WriteLine("{0} : ActiveControl={1} : button1.Focused={2} : textBox1.Focused={3}","textBox1_Validating",ActiveControl.Name ,button1.Focused,textBox1.Focused);

ショートカット1回目
 textBox1_Validating : ActiveControl=textBox1 : button1.Focused=False :
                               textBox1.Focused=True
 button1_Click
 textBox1_Validating : ActiveControl=button1 : button1.Focused=False :
                               textBox1.Focused=True
ショートカット2回目
 textBox1_Validating : ActiveControl=textBox1 : button1.Focused=False :
                               textBox1.Focused=True
 textBox1_Validating : ActiveControl=textBox1 : button1.Focused=False :
                               textBox1.Focused=True

この結果からするとbutton1 にフォーカスは移っていないと思われます。
宜しくお願いします。
ぽぴ王子
ぬし
会議室デビュー日: 2006/03/24
投稿数: 475
お住まい・勤務地: お住まい:城・勤務地:城
投稿日時: 2007-01-17 17:17
まずは再現するミニマムコードと、再現する方法を提示してみると良いかと思います。

SADAS さんのコードをそのまま使用して動かしてみましたが、2回目以降も1回目と
同様の動きになりました。
で。

コード:

    //検証する条件
    if(textBox1.Text == "ERR")
    {
        e.Cancel = true;
    }


こんなところにあからさまに怪しいコードがあるのですが、ここを通っているために
textBox1_Validating から抜け出せていなかったりしませんか?
どこか(この場合は button1_Click あたり)で textBox1.Text = "ERR" のよう
な処理が入っていませんか?ということです。
(実際、そのようなコードを入れたら SADAS さんのおっしゃる現象が再現しました)

そのあたりをよく調べてみてください(本当は他人に見せる前に検証しておくべきか
もしれませんけどね)。
_________________
ぽぴ王子@わんくま同盟
ぽぴ王子の人生プログラミング中 / ぽぴンち。
SADAS
会議室デビュー日: 2007/01/17
投稿数: 4
投稿日時: 2007-01-17 17:48
引用:

ぽぴ王子さんの書き込み (2007-01-17 17:17) より:
まずは再現するミニマムコードと、再現する方法を提示してみると良いかと思います。

SADAS さんのコードをそのまま使用して動かしてみましたが、2回目以降も1回目と
同様の動きになりました。
で。



長くなりますが、以下にコードを書きます。
ただ基本的には、ぽぴ王子さんが試されたのと同じです。
コード:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace ボタンのショートカット
{
	/// <summary>
	/// Form1 の概要の説明です。
	/// </summary>
	public class Form1 : System.Windows.Forms.Form
	{
		private System.Windows.Forms.TextBox textBox1;
		private System.Windows.Forms.Button button1;
		private System.Windows.Forms.Button button2;
		/// <summary>
		/// 必要なデザイナ変数です。
		/// </summary>
		private System.ComponentModel.Container components = null;

		public Form1()
		{
			//
			// Windows フォーム デザイナ サポートに必要です。
			//
			InitializeComponent();

			//
			// TODO: InitializeComponent 呼び出しの後に、コンストラクタ コードを追加してください。
			//
		}

		/// <summary>
		/// 使用されているリソースに後処理を実行します。
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows フォーム デザイナで生成されたコード 
		/// <summary>
		/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
		/// コード エディタで変更しないでください。
		/// </summary>
		private void InitializeComponent()
		{
			this.textBox1 = new System.Windows.Forms.TextBox();
			this.button1 = new System.Windows.Forms.Button();
			this.button2 = new System.Windows.Forms.Button();
			this.SuspendLayout();
			// 
			// textBox1
			// 
			this.textBox1.Location = new System.Drawing.Point(32, 24);
			this.textBox1.Name = "textBox1";
			this.textBox1.TabIndex = 0;
			this.textBox1.Text = "textBox1";
			this.textBox1.Validating += new System.ComponentModel.CancelEventHandler(this.textBox1_Validating);
			// 
			// button1
			// 
			this.button1.Location = new System.Drawing.Point(32, 80);
			this.button1.Name = "button1";
			this.button1.TabIndex = 1;
			this.button1.Text = "&button1";
			this.button1.Click += new System.EventHandler(this.button1_Click);
			// 
			// button2
			// 
			this.button2.Location = new System.Drawing.Point(144, 80);
			this.button2.Name = "button2";
			this.button2.TabIndex = 2;
			this.button2.Text = "閉じる";
			this.button2.Click += new System.EventHandler(this.button2_Click);
			// 
			// Form1
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 12);
			this.ClientSize = new System.Drawing.Size(248, 157);
			this.Controls.Add(this.button2);
			this.Controls.Add(this.button1);
			this.Controls.Add(this.textBox1);
			this.Name = "Form1";
			this.Text = "Form1";
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// アプリケーションのメイン エントリ ポイントです。
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.Run(new Form1());
		}

		private void button2_Click(object sender, System.EventArgs e)
		{
			this.Close();
		}

		private void button1_Click(object sender, System.EventArgs e)
		{
			Console.WriteLine("{0}","button1_Click");
			button1.Select();
		}

		private void textBox1_Validating(object sender, System.ComponentModel.CancelEventArgs e)
		{
			Console.WriteLine("{0} : ActiveControl={1} : button1.Focused={2} : textBox1.Focused={3}","textBox1_Validating",ActiveControl.Name
				,button1.Focused,textBox1.Focused);

			if(ActiveControl.Equals(sender)) return;

			if(textBox1.Text == "ERR")
			{
				MessageBox.Show("ERR");
				e.Cancel = true;
			}
		}
	}
}




再現方法
@テキストボックスに "ERR" と入力します。
Aテキストボックスにカーソルがある状態で「Alt + B」でbutton1を押下します。
Bメッセージボックス"ERR"が表示されて、テキストボックスにカーソルが戻ります。
C再度「Alt + B」でbutton1を押下します。
Dメッセージボックス"ERR"は表示されず、テキストボックスにカーソルがある状態のままです。

Eさらにこの状態で、テキストボックスに"ERR"以外(例"OK")を入力し、「Alt + B」でbutton1を押下しても、button1にカーソルが移動しません。
※本画面を起動直後であれば"ERR"以外(例"OK")を入力した場合、「Alt + B」でbutton1にカーソルが移動します。

以上です。宜しくお願いします。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-01-17 18:29
引用:

SADASさんの書き込み (2007-01-17 13:49) より:

button1.Select();

引用:

e.Cancel = true;


とりあえず、この 2 箇所が、諸悪の根源です。

Validating で検証中にフォーカスを動かすことはしない方が良いです。
(キャンセル時、または、アラートボックスが表示された場合) 予期しないことが起きます。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
ぽぴ王子
ぬし
会議室デビュー日: 2006/03/24
投稿数: 475
お住まい・勤務地: お住まい:城・勤務地:城
投稿日時: 2007-01-17 18:53
コードと再現方法の提示どうもありがとうございます。
私も少しテストしてみました。

…っと、この後にいろいろ書いていましたが、じゃんぬねっとさんがおっしゃられていることで
全て完結してしまいました ○| ̄|_

前回の私のテストでは
  if(ActiveControl.Equals(sender)) return;
を入れていなかったために少し結果に狂いが生じていたようです。すいません。
どちらにしても、button1.Select(); はマズいように思えますね。
上記のコード( ActiveControl をチェックする方法)もいろいろと問題を含んでいるよ
うな気がするので、個人的にはオススメできません。
2回目以降は ActiveControl == textBox1 になるので、エラーチェック自体が処
理されません。
_________________
ぽぴ王子@わんくま同盟
ぽぴ王子の人生プログラミング中 / ぽぴンち。
SADAS
会議室デビュー日: 2007/01/17
投稿数: 4
投稿日時: 2007-01-17 19:35
引用:

じゃんぬねっとさんの書き込み (2007-01-17 18:29) より:

とりあえず、この 2 箇所が、諸悪の根源です。

Validating で検証中にフォーカスを動かすことはしない方が良いです。




引用:

ぽぴ王子さんの書き込み (2007-01-17 18:53) より:

どちらにしても、button1.Select(); はマズいように思えますね。




じゃんぬねっとさん、ぽぴ王子さん、何度もすみません。
Validating で検証中にフォーカス移動するコードがまずいというのは分かりました。

という事は、ショートカットでボタン押下した後、テキストボックスの検証でOKだった場合にボタンにフォーカスを移動させたかったのですが、できない(しないほうがよい?)のでしょうか?


引用:

ぽぴ王子さんの書き込み (2007-01-17 18:53) より:

上記のコード( ActiveControl をチェックする方法)もいろいろと問題を含んでいるよ
うな気がするので、個人的にはオススメできません。




いまValidatingを使用するとき、ActiveControl でチェックしているのですが、もしよろしければお勧めの方法を教えて頂きたいのですが。


宜しくお願いします。

スキルアップ/キャリアアップ(JOB@IT)