WPF .NET 4.0 C#ベースのアプリケーションがあります。ユーザーインターフェイスはXML定義(XAMLではない)から構築しましたが、その下ではWPFを使用してUIを表示しています。つまり、実行時に、XML定義に基づいてWPFUIを作成します。
タブナビゲーションに問題があります。テキストおよびコンボボックスコントロールにTabStop、TabIndexを設定します。
しかし、タブナビゲーションが機能していません。このレイアウトでタブナビゲーションを機能させる方法は?
WPFは、UIツリー全体を単一のタブスコープとして扱います。それはあなたが期待するような小さな領域に分割されていません。これには、UserControls内のコントロールが含まれます。
たとえば、
<StackPanel>
<TextBox Name="TextBox1" />
<MyUserControl />
<TextBox Name="TextBox3" />
</StackPanel>
そしてMyUserControl
は次のようになりました
<MyUserControl>
<TextBox Name="TextBox2" />
</MyUserControl>
デフォルトのタブサイクルは、TextBox1、TextBox2、TextBox3になります。これは、TabIndexプロパティが定義されていないため、すべてのコントロールがデフォルトのタブ順序で実行されます。これは、UIに追加される順序です。
以下のようにコントロールにTabIndexを設定すると、
<StackPanel>
<TextBox Name="TextBox1" TabIndex="1" />
<MyUserControl TabIndex="2" />
<TextBox Name="TextBox3" TabIndex="3" />
</StackPanel>
タブはTextBox1、TextBox3、TextBox2に変わります。これは、TextBox2にTabIndexが指定されていないため、デフォルトが想定され、TabIndexが指定されている他のすべてのコントロールが循環した後にタブが付けられるためです。
私が通常これを回避する方法は、UserControl内のコントロールのTabIndex
をUserControl.TabIndexにバインドすることです。
たとえば、次のバインディングをUserControlに追加すると、タブサイクルが再び正しくなります。
<MyUserControl>
<TextBox Name="TextBox2" TabIndex="{Binding Path=TabIndex, RelativeSource={RelativeSource AncestorType={x:Type local:MyUserControl}}}" />
</MyUserControl>
私は通常、UserControl内のすべてのコントロールにこのバインディングを設定することを覚えておくのではなく、UserControlのLoaded
イベントでこのバインディングを設定することを好みます。これを行うためのより効率的な方法もあると確信していますが、この回避策を回避するために、座ってタブスコープを正しく使用する方法を調査するのに十分な頻度で問題が発生することはありません。
下のボタンも参加させたい場合は、Tree
コントロールまたはStackPanel
派生コントロールのいずれかに KeyboardNavigation.TabNavigation 添付プロパティを設定してみてください。タブサイクル:
<controls:CustomStackPanel KeyboardNavigation.TabNavigation="Cycle">
<Tree>
...
</Tree>
</controls:CustomStackPanel>
ツリーコントロール内のタブの動作を制御するために現在使用しようとしているコードビハインドアプローチと、ツリーコントロール外のタブを処理するためのKeyboardNavigation.TabNavigation
を組み合わせることもできます。
それ自体は答えではありませんが、WPFのタブ移動は非常に面倒です。 XamlでTabNavigation、IsTabStopプロパティを設定し、フォーカススコープをいじる必要があります。 Xamlだけを使用してタブを正しく取得しようと何日も費やしました。 XMLから始めることをお勧めします-> WPFモデルは実際にはXaml-> WPFである必要があります!しかし、それは不可能だと思います。
回避策としてこれはどうですか。生成されたコードでタブを処理することは可能ですか? WPFユーザーコントロールが独自のXMLから独自のソフトウェアによって生成されている場合は、XMLにTabOrder要素を配置し、それを使用してTabOutイベントを接続することをお勧めします。
次のコードサンプルを見て、コード内で移動操作を強制します(タブ移動と同様)。
// Creating a FocusNavigationDirection object to perform the tab operation
// values include Next, Previous, First, Last etc...
FocusNavigationDirection focusDirection = FocusNavigationDirection.Next;
// MoveFocus takes a TraveralReqest as its argument.
TraversalRequest request = new TraversalRequest(focusDirection);
// Gets the element with keyboard focus.
UIElement elementWithFocus = Keyboard.FocusedElement as UIElement;
// Change keyboard focus.
if (elementWithFocus != null)
{
elementWithFocus.MoveFocus(request);
}
次に、「タブ可能」コントロールのKeyUp(またはPreviewKeyUp)イベントに接続し、キーがタブの場合は、上記のコードを呼び出して、フォーカスを次の要素にジャンプさせます。
上記のコードサンプルは、基本的に、WPFが箱から出して何をすべきかをコードで強制します。他のポスターが示唆しているように、生成されたWPFコードを調べて、KeyboardNavigation.IsTabStopとKeyboardNavigation.TabNavigationの値を確認します。
宜しくお願いします、
KeyboardNavigation.TabNavigation = "Once"をお試しください