locked
Silverlight TabItem のフォーカス移動 RRS feed

  • 質問

  • Silverlight を始めたばかりのものです。

    しばらく調べていたのですが、やり方がわからず行き詰ってしまいました。

    Visual Web Developer 2010 Express

    OSはWindows7 で開発しています。

     

    デザイン画面でツールボックスから「TabControl」を追加。

    そこにTabItemを4つほど追加しました。

    <sdk:TabControl Grid.Row="1" HorizontalAlignment="Stretch" Margin="10" Name="tabControl1" VerticalAlignment="Stretch" Width="Auto" IsTabStop="True" TabIndex="2">
       <sdk:TabItem Header="A" Name="tabitem_A" IsTabStop="True" TabIndex="3" />
       <sdk:TabItem Header="B" Name="tabitem_B" IsTabStop="True" TabIndex="4" />
       <sdk:TabItem Header="C" Name="tabitem_C" IsTabStop="True" TabIndex="5" />
       <sdk:TabItem Header="D" Name="tabitem_D" IsTabStop="True" TabIndex="6" />
    </sdk:TabControl>

     

    やりたい事は、キーボードでタブの切り替えです。

    フォーカスがtabitem_A にある時、CTRL+TAB キーで右の tabitem_Bへ

    フォーカスがtabitem_B にある時、SHIFT+CTRL+TAB キーで左の tabitem_Aへ移動させたいです。

     

    1. まずタブオーダーを試しました。CTRキーを使用しないのでやりたい事と違いますが、

       上記のようなXAMLを記述し、別のボタンからTABキーを押下して、

       TabControlへフォーカスが移動した後、もう一度TABキーを押下しても、

       tabitem が切り替わりません。tabitemにタブオーダーの設定は出来ないのでしょうか。

     

    2.プログラムからフォーカスの移動をさせようと以下のように記述しました。

       //tabitem_Aにフォーカスがある時にTABキーを押下すると

       if (this.tabitem_B.Focus() == true)
       {
             MessageBox.Show("成功");
       }
        else
       {
             MessageBox.Show("失敗");
       }

    戻り値が失敗になっており、実際にフォーカスが移動しません。

     

    3. CTRL+TAB でフォーカスを移動させたいので TabControlのKeyDownイベントの処理で以下のように記述しました。

      if( e.Key == Key.Tab )
      {
           if ((Keyboard.Modifiers & ModifierKeys.Shift) > 0)
          {
              MessageBox.Show("ctrl+tab");
          }
          else
          {
                  MessageBox.Show("tab");
           }
      }

    TABキーのみを押下するとTABのKeyDownイベントが発生しますが、CTRLキーを押下した状態でTABキーを押下しても

    KeyDownイベントが発生しません。試しに SHIFT + TAB でやってみるとKeyDownイベントが発生しています。

     

     

    普段、組み込み開発に携わっており、GUIプログラミングが不慣れで初歩的な質問なのかもしれませんが、

    何卒、ご教示のほどよろしくお願いいたします。

     


    2011年2月7日 17:46

回答

  • 例えば、タブアイテムにフォーカスがある状態でエンターキーを押したときに、そのタブアイテムを開く場合、

    private void TabItem_KeyDown(object sender, KeyEventArgs e)
    {
      if (e.Key == Key.Enter)
      {
        // エンターキーが押されたときにそのタブアイテムを選択状態にする。
        var tabItem = sender as TabItem;
        tabItem.IsSelected = true;
      }
    }
    
    などと書けばそのタブアイテムが開きます。

    • 回答としてマーク でぃあい 2011年2月8日 14:23
    • 回答としてマークされていない でぃあい 2011年2月8日 14:27
    • 回答としてマーク でぃあい 2011年2月8日 15:16
    2011年2月8日 3:42
  • 私は単純に

     

    private void TabItem_GotFocus(object sender, RoutedEventArgs e)
    {
      TabItem tabItem = sender as TabItem;
      tabItem.IsSelected = true;
    
      foreach (TabItem ti in this.tabControl1.Items)
      {
        ti.IsTabStop = true;
      }
    }
    

     

    とやったところ、とりあえず動いていました。

    なお、個人的見解ですが、オンブラウザのSilverlightでは、ショートカットキーを使った操作の実現は結構しんどいです。なので、可能ならば、ショートカットキー操作を最小限に仕様を変更したほうが良いかも知れません。

    >自分のGUIプログラミングのわからなさ加減にちょっと壁を感じたりしましたが、やり続けて行こうと思います。

    プログラマの方なら知識のある閾値を超えると急激にいろいろ見えてくる経験があると思います。ぜひSilverlightでも、壁を越えたときの爽快感を味わってほしいです。お互い頑張りましょう!

    • 回答としてマーク でぃあい 2011年2月8日 15:15
    2011年2月8日 14:55

すべての返信

  • 現在フォーカスを持っているコントロールを調べるためにこんなコードを書いてみました。

     

    public MainPage()
    {
      InitializeComponent();
    
      // 500msごとにフォーカスがあるコントロール名を出力ウィンドウに出力する。
      Storyboard sb = new Storyboard();
      sb.Duration = new Duration(TimeSpan.FromMilliseconds(500));
      sb.Completed += (s, e) =>
      {
        // 現在フォーカスがあるコントロールを取得する。
        var obj = FocusManager.GetFocusedElement();
        var var = obj as FrameworkElement;
        if (var != null)
        {
          System.Diagnostics.Debug.WriteLine(var.Name + "(" + var.GetType().Name + ")");
        }
        else
        {
          System.Diagnostics.Debug.WriteLine("null");
        }
    
        sb.Begin();
      };
    
      sb.Begin();
    }
    

     

    すると、Tabキーでフォーカス自体は、TabItemに行ってるみたいです。デバッグの参考になればと幸いです。

    また、CTRL+TAB キーはブラウザ自体がフックしてしまい、Silverlightに通知が行っていないようです。オンブラウザのSilverlightの場合、ファンクションキーなど結構多くのキーがブラウザなどに取られてしまい使えないことがあるので、先にどのキーが使えるかを調査してから、キー動作を決めたほうが良いと思います。

    2011年2月8日 1:01
  • お世話になります。

    レスありがとうございます。

     

    >また、CTRL+TAB キーはブラウザ自体がフックしてしまい、Silverlightに通知が行っていないようです。オンブラウザのSilverlightの場合、ファンク ションキーなど結構多くのキーがブラウザなどに取られてしまい使えないことがあるので、先にどのキーが使えるかを調査してか

     

    なるほど、ブラウザとの兼ねあいを考えなければいけないのですね。

    ありがとうございます。いろいろ調査してみます。

     

    >すると、Tabキーでフォーカス自体は、TabItemに行ってるみたいです。デバッグの参考になればと幸いです。

     

    タブオーダーではフォーカスが切り替わっているが、TAB画面自体は切り替わっていないのですね。

    では、TABの画面を切り替えるにはどうすれば良いのでしょうか。

    マウスでやればもちろん切り替わるのですが、キーボードで切り替えられないと

    使い勝手が悪いです・・・。

    自分でも、もう少し調べてみます。

     

    ご教示ありがとうございました。

    大変参考になりました。

     


    2011年2月8日 3:05
  • 例えば、タブアイテムにフォーカスがある状態でエンターキーを押したときに、そのタブアイテムを開く場合、

    private void TabItem_KeyDown(object sender, KeyEventArgs e)
    {
      if (e.Key == Key.Enter)
      {
        // エンターキーが押されたときにそのタブアイテムを選択状態にする。
        var tabItem = sender as TabItem;
        tabItem.IsSelected = true;
      }
    }
    
    などと書けばそのタブアイテムが開きます。

    • 回答としてマーク でぃあい 2011年2月8日 14:23
    • 回答としてマークされていない でぃあい 2011年2月8日 14:27
    • 回答としてマーク でぃあい 2011年2月8日 15:16
    2011年2月8日 3:42
  • 再びのご回答ありがとうございます。

     

    KeyDownイベント発生時にTaItemのそれぞれのプロパティをテキストボックスに表示させました。

    それにより、タブオーダーでフォーカスを移動させた場合、KeyDownのイベント発生時点では、

    まだ隣のタブにフォーカスが移動していないことを理解しました。

    よって、KeyDownイベント時ではなく、GetFocusイベント発生時に

     private void tabItem_GetFocus(object sender, RoutedEventArgs e)
     {
          TabItem tabItem = sender as TabItem;

          tabItem.IsSelected = true;
     }

    としてやることで、TABキーの押下ごとに右隣のタブが表示され

    意図通りに動作したかに思えました。

     

    しかし、ここで問題が。。。

     

    SHIFT+TABキーで、左のタブに戻れない。

    やっと理解したのは、一度表示していたタブのIsTabstopプロパティ が

    右のタブに移動した瞬間、勝手に false になってしまいます。

    これを防ぐ方法ってあるでしょうか。

    関係あるかなと思ったのはTabNavigationプロパティで、

    TabControl、TaItem共に"LOCAL" に設定してみましたが関係ありませんでした。

    最終手段はIsTabstop をtrue にセットし直す方法はあるとは思いますがそれはmustでしょうか。

     

    よろしくお願い致します。

     


    2011年2月8日 10:21
  • >一度表示していたタブのIsTabstopプロパティ が右のタブに移動した瞬間、勝手に false になってしまいます。
    この現象を確認ししました。はじめて知ったのですが、不思議な仕様ですね。
    申し訳ありませんが、私もIsTabstopを明示的にtrueにする方法しか思いつきませんでした。
    2011年2月8日 14:18
  • ありがとうございました。

    とても勉強になりました。

    自分のGUIプログラミングのわからなさ加減に

    ちょっと壁を感じたりしましたが、やり続けて行こうと思います。

     

     

    試しにLostFocus時にIsTabstop にtrue をセットしてみましたが問題解決しませんでした。

    動くようにするやりようはあると思いますが、この辺の仕様、又はIsTabstop が falseにならない方法など

    ご存知の方いらっしゃればよろしくお願いします。

    また、参考URLや資料などお教えいただければ幸いです。

    自分でもNETなど一応見てるのですが、中々解決に至らず・・。

    よろしくお願いいたします。

     

     


    2011年2月8日 14:23
  • 私は単純に

     

    private void TabItem_GotFocus(object sender, RoutedEventArgs e)
    {
      TabItem tabItem = sender as TabItem;
      tabItem.IsSelected = true;
    
      foreach (TabItem ti in this.tabControl1.Items)
      {
        ti.IsTabStop = true;
      }
    }
    

     

    とやったところ、とりあえず動いていました。

    なお、個人的見解ですが、オンブラウザのSilverlightでは、ショートカットキーを使った操作の実現は結構しんどいです。なので、可能ならば、ショートカットキー操作を最小限に仕様を変更したほうが良いかも知れません。

    >自分のGUIプログラミングのわからなさ加減にちょっと壁を感じたりしましたが、やり続けて行こうと思います。

    プログラマの方なら知識のある閾値を超えると急激にいろいろ見えてくる経験があると思います。ぜひSilverlightでも、壁を越えたときの爽快感を味わってほしいです。お互い頑張りましょう!

    • 回答としてマーク でぃあい 2011年2月8日 15:15
    2011年2月8日 14:55
  • 最後まで解説ありがとうございました。

     

    私もその後少し試して、IsTabStopがfalseに切り替わるタイミングは

    フォーカスが移ったtabItemの IsSelected を true にセットした時だと理解しました。

     

    >なお、個人的見解ですが、オンブラウザのSilverlightでは、ショートカットキーを使った操作の実現は結構しんどいです。なので、可能ならば、ショートカットキー操作を最小限に仕様を変更したほうが良いかも知れません。

     

    ありがとうございます。

    すごく参考になりました。

     

    仕事はC言語でガリガリやってるだけで、GUIはまだ始めたばかりで趣味の範囲ですが、

    めげずに続けようと思います。

     

    とりあえずすっきりしました。

    ありがとうございました。

     


    2011年2月8日 15:15