次の方法で共有


フォーカスの概要

WPF には、フォーカスに関連する主な概念として、キーボード フォーカスと論理フォーカスの 2 つがあります。 キーボード フォーカスとは、キーボード入力を受け取る要素を指し、論理フォーカスはフォーカスのあるフォーカス スコープ内の要素を指します。 これらの概念については、この概要で詳しく説明します。 これらの概念の違いを理解することは、フォーカスを取得できる複数の領域を持つ複雑なアプリケーションを作成するために重要です。

フォーカス管理に参加する主要なクラスは、Keyboard クラス、FocusManager クラス、基本要素クラス (UIElementContentElementなど) です。 基本要素の詳細については、「基本要素の概要」を参照してください。

Keyboard クラスは主にキーボード フォーカスに関係し、FocusManager は主に論理フォーカスに関係しますが、これは絶対的な区別ではありません。 キーボード フォーカスを持つ要素にも論理フォーカスがありますが、論理フォーカスを持つ要素には必ずしもキーボード フォーカスがありません。 これは、Keyboard クラスを使用してキーボード フォーカスを持つ要素を設定する場合に明らかです。これにより、要素に論理的なフォーカスも設定されます。

キーボード フォーカス

キーボード フォーカスは、現在キーボード入力を受け取っている要素を指します。 キーボード フォーカスを持つ要素は、デスクトップ全体に 1 つだけ存在できます。 WPF では、キーボード フォーカスを持つ要素 IsKeyboardFocusedtrueに設定されます。 Keyboard クラスの静的プロパティ FocusedElement は、現在キーボード フォーカスがある要素を取得します。

要素がキーボード フォーカスを取得するには、基本要素の Focusable プロパティと IsVisible プロパティを trueに設定する必要があります。 Panel 基底クラスなど、一部のクラスでは、Focusable が既定で false に設定されています。そのため、このような要素がキーボードフォーカスを取得できるようにするには、Focusabletrue に設定する必要があります。

キーボード フォーカスは、要素へのタブ移動や特定の要素でのマウスのクリックなど、UI とのユーザー操作を通じて取得できます。 キーボード フォーカスは、Keyboard クラスの Focus メソッドを使用してプログラムで取得することもできます。 Focus メソッドは、指定した要素にキーボード フォーカスを与えようとします。 返される要素はキーボード フォーカスを持つ要素です。これは、古いフォーカス オブジェクトまたは新しいフォーカス オブジェクトが要求をブロックした場合、要求とは異なる要素である可能性があります。

次の例では、Focus メソッドを使用して、Buttonにキーボード フォーカスを設定します。

private void OnLoaded(object sender, RoutedEventArgs e)
{
    // Sets keyboard focus on the first Button in the sample.
    Keyboard.Focus(firstButton);
}
Private Sub OnLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
    ' Sets keyboard focus on the first Button in the sample.
    Keyboard.Focus(firstButton)
End Sub

基本要素クラスの IsKeyboardFocused プロパティは、要素にキーボード フォーカスがあるかどうかを示す値を取得します。 基本要素クラスの IsKeyboardFocusWithin プロパティは、要素またはそのビジュアル子要素のいずれかがキーボード フォーカスを持っているかどうかを示す値を取得します。

アプリケーションの起動時に初期フォーカスを設定する場合、フォーカスを受け取る要素は、アプリケーションによって読み込まれた初期ウィンドウのビジュアル ツリーに存在する必要があり、要素は Focusable し、IsVisibletrueに設定する必要があります。 初期フォーカスを設定する推奨される場所は、Loaded イベント ハンドラーにあります。 Dispatcher コールバックは、Invoke または BeginInvokeを呼び出すことによっても使用できます。

論理フォーカス

論理フォーカスとは、フォーカス スコープ内の FocusManager.FocusedElement を指します。 フォーカス スコープは、スコープ内の FocusedElement を追跡する要素です。 キーボード フォーカスがフォーカス スコープから離れると、フォーカスされた要素はキーボード フォーカスを失いますが、論理フォーカスは保持されます。 キーボード フォーカスがフォーカス スコープに戻ると、フォーカスされた要素はキーボード フォーカスを取得します。 これにより、複数のフォーカス スコープ間でキーボード フォーカスを変更できますが、フォーカスがフォーカススコープに戻ったときに、フォーカススコープ内のフォーカスされた要素がキーボードフォーカスを回復することを保証します。

アプリケーションには論理フォーカスを持つ複数の要素を含めることができますが、特定のフォーカス スコープに論理フォーカスを持つ要素は 1 つだけ存在する可能性があります。

キーボード フォーカスを持つ要素には、その要素が属するフォーカス スコープの論理フォーカスがあります。

要素は、FocusManager 添付プロパティ IsFocusScopetrueに設定することで、Extensible Application Markup Language (XAML) のフォーカス スコープに変換できます。 コードでは、SetIsFocusScopeを呼び出すことによって、要素をフォーカス スコープに変換できます。

次の例では、IsFocusScope 添付プロパティを設定して、StackPanel をフォーカス スコープにします。

<StackPanel Name="focusScope1" 
            FocusManager.IsFocusScope="True"
            Height="200" Width="200">
  <Button Name="button1" Height="50" Width="50"/>
  <Button Name="button2" Height="50" Width="50"/>
</StackPanel>
StackPanel focuseScope2 = new StackPanel();
FocusManager.SetIsFocusScope(focuseScope2, true);
Dim focuseScope2 As New StackPanel()
FocusManager.SetIsFocusScope(focuseScope2, True)

GetFocusScope は、指定した要素のフォーカス スコープを返します。

既定でフォーカス スコープである WPF のクラスは、WindowMenuItemToolBar、および ContextMenuです。

GetFocusedElement は、指定したフォーカス スコープのフォーカスされた要素を取得します。 SetFocusedElement 指定したフォーカス スコープ内のフォーカスされた要素を設定します。 SetFocusedElement は、通常、最初にフォーカスされた要素を設定するために使用されます。

次の例では、フォーカス対象の要素をフォーカス スコープに設定し、フォーカス スコープのフォーカスされた要素を取得します。

// Sets the focused element in focusScope1
// focusScope1 is a StackPanel.
FocusManager.SetFocusedElement(focusScope1, button2);

// Gets the focused element for focusScope 1
IInputElement focusedElement = FocusManager.GetFocusedElement(focusScope1);
' Sets the focused element in focusScope1
' focusScope1 is a StackPanel.
FocusManager.SetFocusedElement(focusScope1, button2)

' Gets the focused element for focusScope 1
Dim focusedElement As IInputElement = FocusManager.GetFocusedElement(focusScope1)

キーボード ナビゲーション

KeyboardNavigation クラスは、ナビゲーション キーのいずれかが押されたときに、既定のキーボード フォーカス ナビゲーションを実装します。 ナビゲーション キーは、TAB、Shift + Tab、Ctrl + Tab、Ctrl + Shift + Tab、UPARROW、DOWNARROW、LEFTARROW、RIGHTARROW キーです。

ナビゲーション コンテナーのナビゲーション動作は、添付 KeyboardNavigation プロパティ TabNavigationControlTabNavigation、および DirectionalNavigationを設定することで変更できます。 これらのプロパティは KeyboardNavigationMode 型であり、使用可能な値は、ContinueLocalContainedCycleOnce、および Noneです。 既定値は Continueです。これは、要素がナビゲーション コンテナーではないことを意味します。

次の例では、多数の MenuItem オブジェクトを含む Menu を作成します。 TabNavigation 添付プロパティは、MenuCycle に設定されます。 Menu内のタブ キーを使用してフォーカスが変更されると、フォーカスは各要素から移動し、最後の要素に到達すると、フォーカスは最初の要素に戻ります。

<Menu KeyboardNavigation.TabNavigation="Cycle">
  <MenuItem Header="Menu Item 1" />
  <MenuItem Header="Menu Item 2" />
  <MenuItem Header="Menu Item 3" />
  <MenuItem Header="Menu Item 4" />
</Menu>
Menu navigationMenu = new Menu();
MenuItem item1 = new MenuItem();
MenuItem item2 = new MenuItem();
MenuItem item3 = new MenuItem();
MenuItem item4 = new MenuItem();

navigationMenu.Items.Add(item1);
navigationMenu.Items.Add(item2);
navigationMenu.Items.Add(item3);
navigationMenu.Items.Add(item4);

KeyboardNavigation.SetTabNavigation(navigationMenu,
    KeyboardNavigationMode.Cycle);
Dim navigationMenu As New Menu()
Dim item1 As New MenuItem()
Dim item2 As New MenuItem()
Dim item3 As New MenuItem()
Dim item4 As New MenuItem()

navigationMenu.Items.Add(item1)
navigationMenu.Items.Add(item2)
navigationMenu.Items.Add(item3)
navigationMenu.Items.Add(item4)

KeyboardNavigation.SetTabNavigation(navigationMenu, KeyboardNavigationMode.Cycle)

フォーカスを操作するための追加の API は、MoveFocusPredictFocusです。

MoveFocus は、アプリケーション内の次の要素にフォーカスを変更します。 TraversalRequest を使用して方向を指定します。 MoveFocus に渡される FocusNavigationDirection は、FirstLastUpDownなど、フォーカスを移動できるさまざまな方向を指定します。

次の例では、MoveFocus を使用してフォーカスされた要素を変更します。

// Creating a FocusNavigationDirection object and setting it to a
// local field that contains the direction selected.
FocusNavigationDirection focusDirection = _focusMoveValue;

// 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);
}
' Creating a FocusNavigationDirection object and setting it to a
' local field that contains the direction selected.
Dim focusDirection As FocusNavigationDirection = _focusMoveValue

' MoveFocus takes a TraveralReqest as its argument.
Dim request As New TraversalRequest(focusDirection)

' Gets the element with keyboard focus.
Dim elementWithFocus As UIElement = TryCast(Keyboard.FocusedElement, UIElement)

' Change keyboard focus.
If elementWithFocus IsNot Nothing Then
    elementWithFocus.MoveFocus(request)
End If

PredictFocus は、フォーカスが変更された場合にフォーカスを受け取るオブジェクトを返します。 現在、PredictFocusでは、UpDownLeft、および Right のみがサポートされています。

フォーカス イベント

キーボード フォーカスに関連するイベントは、PreviewGotKeyboardFocusGotKeyboardFocusPreviewLostKeyboardFocusLostKeyboardFocusです。 イベントは、Keyboard クラスの添付イベントとして定義されますが、基底要素クラスの同等のルーティング イベントとして簡単にアクセスできます。 イベントの詳細については、「ルーティング イベントの概要」を参照してください。

GotKeyboardFocus は、要素がキーボード フォーカスを取得するときに発生します。 LostKeyboardFocus は、要素がキーボード フォーカスを失ったときに発生します。 PreviewGotKeyboardFocus イベントまたは PreviewLostKeyboardFocusEvent イベントが処理され、Handledtrueに設定されている場合、フォーカスは変更されません。

次の例では、GotKeyboardFocus イベント ハンドラーと LostKeyboardFocus イベント ハンドラーを TextBoxにアタッチします。

<Border BorderBrush="Black" BorderThickness="1"
        Width="200" Height="100" Margin="5">
  <StackPanel>
    <Label HorizontalAlignment="Center" Content="Type Text In This TextBox" />
    <TextBox Width="175"
             Height="50" 
             Margin="5"
             TextWrapping="Wrap"
             HorizontalAlignment="Center"
             VerticalScrollBarVisibility="Auto"
             GotKeyboardFocus="TextBoxGotKeyboardFocus"
             LostKeyboardFocus="TextBoxLostKeyboardFocus"
             KeyDown="SourceTextKeyDown"/>
  </StackPanel>
</Border>

TextBox がキーボード フォーカスを取得すると、TextBoxBackground プロパティが LightBlueに変更されます。

private void TextBoxGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    TextBox source = e.Source as TextBox;

    if (source != null)
    {
        // Change the TextBox color when it obtains focus.
        source.Background = Brushes.LightBlue;

        // Clear the TextBox.
        source.Clear();
    }
}
Private Sub TextBoxGotKeyboardFocus(ByVal sender As Object, ByVal e As KeyboardFocusChangedEventArgs)
    Dim source As TextBox = TryCast(e.Source, TextBox)

    If source IsNot Nothing Then
        ' Change the TextBox color when it obtains focus.
        source.Background = Brushes.LightBlue

        ' Clear the TextBox.
        source.Clear()
    End If
End Sub

TextBox がキーボード フォーカスを失うと、TextBoxBackground プロパティが白に戻ります。

private void TextBoxLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    TextBox source = e.Source as TextBox;

    if (source != null)
    {
        // Change the TextBox color when it loses focus.
        source.Background = Brushes.White;

        // Set the  hit counter back to zero and updates the display.
        this.ResetCounter();
    }
}
Private Sub TextBoxLostKeyboardFocus(ByVal sender As Object, ByVal e As KeyboardFocusChangedEventArgs)
    Dim source As TextBox = TryCast(e.Source, TextBox)

    If source IsNot Nothing Then
        ' Change the TextBox color when it loses focus.
        source.Background = Brushes.White

        ' Set the  hit counter back to zero and updates the display.
        Me.ResetCounter()
    End If
End Sub

論理フォーカスに関連するイベントは GotFocusLostFocusです。 これらのイベントは、アタッチされたイベントとして FocusManager で定義されますが、FocusManager は CLR イベント ラッパーを公開しません。 UIElementContentElement は、これらのイベントをより便利に公開します。

関連項目