DOBON.NET DOBON.NETプログラミング掲示板過去ログ

SelectTab後のフォーカス

環境/言語:[Windows7 VB.NET 2013]
分類:[.NET]

TabControl のページを SelectTab や SelectedIndex で変更した場合、そのページ内のコントロールにフォーカスが移動してしまいます。
フォーカスを移動させずにページのみ変更させる方法はないのでしょうか?
SelectTab や SelectedIndexでの変更後に、TabControlにフォーカスを
当てる様にしてみてはいかがでしょうか。
TabPage 内のコントロールの Enter イベントで何らかの処理(ポップアップメッセージを表示する等)を行っていると、SelectTab 後にフォーカスを移動してもその処理が動作してしまうのを防ぎたいのです。
単純に TabPage を切り替えたいだけなのに、フォーカスが移動してしまうのは防げないのでしょうか?
■No32585に返信(おまつさんの記事)
> TabControl のページを SelectTab や SelectedIndex で変更した場合、そのページ内のコントロールにフォーカスが移動してしまいます。
> フォーカスを移動させずにページのみ変更させる方法はないのでしょうか?

タブを切り替える前に、ページ上のコントロール群の
TabStop あるいは Enabled を False にしておき、
切り替えた後で、それらを復元することで対応できないでしょうか。

実験的に、『PabPage3.Activate()』の形式で利用可能な
拡張メソッドを用意してみました。

Module TabControlExtension

    <System.Runtime.CompilerServices.Extension()> _
    Public Sub Activate(page As TabPage)
        For Each c In page.Controls.OfType(Of Control)()
            c.Tag = c.TabStop
            c.TabStop = False
        Next
        DirectCast(page.Parent, TabControl).SelectTab(page)
        For Each c In page.Controls.OfType(Of Control)()
            If TypeOf c.Tag Is Boolean Then
                c.TabStop = CBool(c.Tag)
            End If
        Next
    End Sub

End Module
■No32592に追記(魔界の仮面弁士の記事)
>   c.Tag = c.TabStop

手抜きで Tag プロパティに管理させてしまいましたが、これだと
Tag プロパティを別の目的で使っている場合に競合しますね…。


ということで修正版。

TabStop の一時保存先を、そのコントロールの Tag プロパティに
置いておくのではなく、ローカル変数(Dictionary)に溜め込むように
修正してみました。


<System.Runtime.CompilerServices.Extension()> _
Public Sub Activate(page As TabPage)
    Dim cache As New Dictionary(Of Control, Boolean)()
    For Each c As Control In page.Controls
        cache(c) = c.TabStop
        c.TabStop = False
    Next
    DirectCast(page.Parent, TabControl).SelectTab(page)
    For Each x In cache
        x.Key.TabStop = x.Value
    Next
End Sub


提示のサンプルでは、拡張メソッドを TabPage 側に追加していますが、
もしも使いにくいようであれば TabControl 側に実装してみてください。

思いつきで組んだだけで、さほどテストはしていません。
一応、手元の環境では TabPage 直下のコントロールに対する
TabStop だけでうまく切り替えられているように見えますが、
もしもそれでは不足だった場合には、Enabled を使うなど、
適宜調整してみてください。



-- 以下余談 --
今回の処理は元々、Selecting / Selected イベントで処理させようと
したのですが、コードで TabPage を切りかえた場合は、このイベントが
発生しなかったため、ページ切替処理ごと作りこむ実装としています。

そこでまずは、継承して作りこみはじめたのですが、残念ながら
SelectTab メソッドは Overridable では無かったので、実装しようにも
シャドウイングするか、別メソッドにするしかありませんでした。

で、どうせ別メソッドにするなら、継承せずとも拡張メソッドで
十分だろうということで、今回の形にしています。
  • 題名: Re[3]: SelectTab後のフォーカス
  • 著者: おまつ
  • 日時: 2014/09/06 13:49:15
  • ID: 32597
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
サンプルコードありがとうございます。
TabStopの制御で実現してみたいと思います。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板