2011-02-10 10 views
5

フォーカスとキーボードのナビゲーションに奇妙な動作が見られます。下の例では、ItemsSourceにバインドされたCheckBoxのリストを表示するように、テンプレート化された単純なItemsControlがあります。 FocusManager.IsFocusScope =「True」を割り当てがキーボードフォーカスをする際のチェックのItemsControlの外にジャンプするマウスクリックを経由して、フォーカスのためのチェックボックスをチェックするときに設定することが失敗する原因となるいくつかの奇妙な理由でシンプルなWPF ItemsControlの奇妙なフォーカス動作

<ItemsControl FocusManager.IsFocusScope="True" 
       ItemsSource="{Binding ElementName=TheWindow, Path=ListOStrings}"> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <CheckBox Content="{Binding}" /> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

ボックスのスペースバーを使用してチェックされます。どちらの症状も、チェックボックスをオンにしたときに起きる奇妙なナビゲーションを指しているようですが、その底に苦労しています。

この問題は、このメソッドを使用してビジュアルツリーの上に親要素をフォーカススコープとして設定した場合に発生します。 FocusManager.IsFocusScope = "True"を削除すると問題が解決します。残念ながら、私は他のフォーカス関連の結果を心配することなく、これらのフォーカススコープを削除することができない大きなプロジェクトでこの問題を認識しています。

誰かが私に見ている奇妙な行動を私に説明できますか?これはバグですか、何かが完全に欠けていますか?

答えて

16

この記事は非常によく、それを説明する:http://www.codeproject.com/KB/WPF/EnhancedFocusScope.aspx

何のためFocusScopeがデザインされたのですか?

マイクロソフトでは、WPFでFocusScopeを使用して、 一時的なセカンダリフォーカスを作成します。 WPFの各ツールバーとメニューには、 独自のフォーカススコープがあります。この知識を用いて

、我々はこれらの問題を持っている理由我々は明らかに は見ることができます:ツールバーのボタンは、それ自体に コマンドを実行するべきではありません

が、ツールバーの前に焦点を当てていたものは何でも に がクリックされました。これを達成するために、 コマンドは、フォーカス スコープからフォーカスを無視し、代わりに 'メイン'論理 フォーカスを使用します。これは、なぜ ルーティングされたコマンドが フォーカススコープ内で動作しないのかを説明します。

テストアプリケーションのスクリーンショットの大きなテキストボックスにまだ のキャレットが表示されるのはなぜですか?私はこれに答えて を知らないのですが、それはなぜですか? テキストボックスに キーボードフォーカスがありません( の小さなテキストボックスにWPFフォーカススコープがあります)。 はまだアクティブなウィンドウである に主な論理的な焦点を持ち、すべてのルーティングされたコマンドの受信者 です。

そして、この部分は、あなたが

なぜ にキーボードフォーカスの移動大きなテキストボックスあなたがWPFで チェックボックスのタブにフォーカス時にスコープと を見ている行動をカバースペースを押して切り替えますか?

メニュー項目またはツールバーの をクリックすると、これはまさに となります。キーボードのフォーカスは に戻ります。すべて ButtonBaseから派生したコントロールは これを行います。

+0

+1この問題の説明は、私はちょうどIsEnhancedFocusScopeの実装を追加しました。 –

+4

私がまだ説明していないのは、ボタンとチェックボックスである子どもたちの集まりをフォーカススコープにする別の例を取り上げると、これらのうちの1つをクリックするとチェックボックスItemsControlに表示されるフォーカスの振る舞いが奇妙に失われることはありません。なぜこれはItemsControl内のチェックボックスに影響するように見えますか?ScrollViewer、ItemsPresenter、...と何か関係ありますか? – jpierson

8

@Meleakは問題を非常にうまく説明しました。問題の内容と解決方法を完全に理解するには、http://www.codeproject.com/KB/WPF/EnhancedFocusScope.aspxの記事をお読みください。

<ItemsControl my:FocusExtensions.IsEnhancedFocusScope="True" 
       ItemsSource="{Binding ElementName=TheWindow, Path=ListOStrings}"> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <CheckBox Content="{Binding}" /> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

それは動作します:あなただけの標準IsFocusScopeプロパティの代わりにこの添付プロパティを設定する必要があなたのXAMLで

public static class FocusExtensions 
{ 
    private static bool SettingKeyboardFocus { get; set; } 

    public static bool GetIsEnhancedFocusScope(DependencyObject element) { 
     return (bool)element.GetValue(IsEnhancedFocusScopeProperty); 
    } 

    public static void SetIsEnhancedFocusScope(DependencyObject element, bool value) { 
     element.SetValue(IsEnhancedFocusScopeProperty, value); 
    } 

    public static readonly DependencyProperty IsEnhancedFocusScopeProperty = 
     DependencyProperty.RegisterAttached(
      "IsEnhancedFocusScope", 
      typeof(bool), 
      typeof(FocusExtensions), 
      new UIPropertyMetadata(false, OnIsEnhancedFocusScopeChanged)); 

    private static void OnIsEnhancedFocusScopeChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e) { 
     var item = depObj as UIElement; 
     if (item == null) 
      return; 

     if ((bool)e.NewValue) { 
      FocusManager.SetIsFocusScope(item, true); 
      item.GotKeyboardFocus += OnGotKeyboardFocus; 
     } 
     else { 
      FocusManager.SetIsFocusScope(item, false); 
      item.GotKeyboardFocus -= OnGotKeyboardFocus; 
     } 
    } 

    private static void OnGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) { 
     if (SettingKeyboardFocus) { 
      return; 
     } 

     var focusedElement = e.NewFocus as Visual; 

     for (var d = focusedElement; d != null; d = VisualTreeHelper.GetParent(d) as Visual) { 
      if (FocusManager.GetIsFocusScope(d)) { 
       SettingKeyboardFocus = true; 

       try { 
        d.SetValue(FocusManager.FocusedElementProperty, focusedElement); 
       } 
       finally { 
        SettingKeyboardFocus = false; 
       } 

       if (!(bool)d.GetValue(IsEnhancedFocusScopeProperty)) { 
        break; 
       } 
      } 
     } 
    } 
} 

:私はちょうど資料に記載IsEnhancedFocusScope添付行動の完全な実装を追加しますフォーカススコープが機能することを期待しています。