none
ToolStripButtonを押すと他のコントロールの変更をコミットせずにイベント飛んでくる RRS feed

  • 質問

  • いつもお世話になっております。
    環境VS2005 C# WinXP

    DateTimePickerとButtonを配置し、
    DateTimePickerの値を変更している最中にボタンを押すと
    DateTimePickerからフォーカスが外れるので
    その変更がコミットされて、ボタンのイベントハンドラではコミット後の値を取得することが出来ます。

    ところがButtonをToolStripButtonにすると
    コミットされずに、ToolStripButtonのClickイベントハンドラ内で
    DateTimePickerの値を取得しようとすると、
    コミットされていない古い値が返されます。

    ToolStripButtonにフォーカスが当たっているにも関わらず、
    DateTimePickerからフォーカスが抜けていないようにも見えます。
    DateTimePickerには強制的にコミットさせるようなメソッドも見当たらず、
    悩んでいるという状況です。
    宜しくお願い致します。


    2009年5月1日 11:34

回答

  • 以下が参考になります。

    toolstrip question
    http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/31fb1920-fc28-4c6d-befe-bd76d68b4c57/

    ToolStripItemsはWindowsコントロールではないため、フォーカスを受け取らないようです。したがって、ToolStripButtonのクリックイベントで何か他のコントロールへフォーカスを当てることで解決しています。上記の例では、ButtonコントロールのLeftプロパティを十分大きなマイナス値にして画面の外に配置し、そのButtonコントロールにフォーカスを当てるようにしています。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク Myon 2009年5月3日 8:39
    2009年5月1日 22:45
    モデレータ
  • trapemiyaさん、ご回答ありがとうございました。解決いたしました。
    自分の調査不足を実感しておりますが、
    同様の問題で悩んでおられる方が結構いらっしゃることがわかりました。

    http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=44219&forum=7

    http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_22967093.html

    http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/64a4ddaa-7be5-4936-bb2a-9c0c47532e7a

    ボタンを配置する手もあるのですが、今回は以下の方法を採用いたしました。



      private void toolStripButton1_Click( object sender, EventArgs e )
      {
       // これで強制的にグリッドのValidationを実行
       bool bRet = ( ( Form )toolStripButton1.Owner.Parent ).Validate();
       if( bRet == false ) return;

       // ツールバーにフォーカスを当ててDateTimePickerの変更をコミット
       toolStripButton1.Owner.Focus();

       // コミットされた値を取得
       DateTime t = dateTimePicker1.Value;
      }



    toolStripが好きで多用していたのですが、思わぬ落とし穴でした。
    MenuStripにも同様のことが言えるようです。
    画面には大量のtoolStripItemやMenuStripItemがあり、
    あちらこちらでValidationを行っているため、上記の処理をサブクラス化して
    作り直すことを検討しております。
    それにしてもToolStripComboBoxはちゃんと動くのに、なんでToolStripButtonだけが、、、

    • 回答としてマーク Myon 2009年5月3日 8:39
    • 編集済み Myon 2009年5月6日 4:04
    2009年5月3日 6:59

すべての返信

  • あと、それに似た問題で、
    DataGridViewのCellValidatingイベントで
    e.Cancel = true;
    としている場合、
    セルの値を修正するまで他のコントロールは一切触れなくなりますが、
    ToolStripButtonだけは普通に押せてしまいます。
    (ToolStripComboBoxも触れなくなるので問題なし。)

    これも何とかならないものでしょうか。

    2009年5月1日 15:57
  • 以下が参考になります。

    toolstrip question
    http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/31fb1920-fc28-4c6d-befe-bd76d68b4c57/

    ToolStripItemsはWindowsコントロールではないため、フォーカスを受け取らないようです。したがって、ToolStripButtonのクリックイベントで何か他のコントロールへフォーカスを当てることで解決しています。上記の例では、ButtonコントロールのLeftプロパティを十分大きなマイナス値にして画面の外に配置し、そのButtonコントロールにフォーカスを当てるようにしています。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク Myon 2009年5月3日 8:39
    2009年5月1日 22:45
    モデレータ
  • trapemiyaさん、ご回答ありがとうございました。解決いたしました。
    自分の調査不足を実感しておりますが、
    同様の問題で悩んでおられる方が結構いらっしゃることがわかりました。

    http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=44219&forum=7

    http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_22967093.html

    http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/64a4ddaa-7be5-4936-bb2a-9c0c47532e7a

    ボタンを配置する手もあるのですが、今回は以下の方法を採用いたしました。



      private void toolStripButton1_Click( object sender, EventArgs e )
      {
       // これで強制的にグリッドのValidationを実行
       bool bRet = ( ( Form )toolStripButton1.Owner.Parent ).Validate();
       if( bRet == false ) return;

       // ツールバーにフォーカスを当ててDateTimePickerの変更をコミット
       toolStripButton1.Owner.Focus();

       // コミットされた値を取得
       DateTime t = dateTimePicker1.Value;
      }



    toolStripが好きで多用していたのですが、思わぬ落とし穴でした。
    MenuStripにも同様のことが言えるようです。
    画面には大量のtoolStripItemやMenuStripItemがあり、
    あちらこちらでValidationを行っているため、上記の処理をサブクラス化して
    作り直すことを検討しております。
    それにしてもToolStripComboBoxはちゃんと動くのに、なんでToolStripButtonだけが、、、

    • 回答としてマーク Myon 2009年5月3日 8:39
    • 編集済み Myon 2009年5月6日 4:04
    2009年5月3日 6:59