次の方法で共有


フォーカスの概要

更新 : 2007 年 11 月

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

フォーカス管理に関与する主要なクラスには、Keyboard クラス、FocusManager クラス、および UIElementContentElement などの基本要素クラスがあります。基本要素の詳細については、「基本要素の概要」を参照してください。

Keyboard クラスは主にキーボード フォーカスに関連し、FocusManager は主に論理フォーカスに関連しますが、これは絶対的な区別ではありません。キーボード フォーカスを持つ要素は論理フォーカスも持ちますが、論理フォーカスを持つ要素は必ずしもキーボード フォーカスを持ちません。Keyboard クラスを使用してキーボード フォーカスを持つ要素を設定したときには、要素に論理フォーカスも設定されるので、この違いがよくわかります。

このトピックには次のセクションが含まれています。

  • キーボード フォーカス
  • 論理フォーカス
  • キーボード ナビゲーション
  • プログラムによるフォーカスのナビゲーション
  • フォーカス イベント
  • 関連トピック

キーボード フォーカス

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

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

キーボード フォーカスは、要素への Tab キーでの移動や特定の要素でのマウスのクリックなど、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);
}

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

アプリケーションの起動時に初期フォーカスを設定する場合、フォーカスを受け取る要素を PresentationSource に接続し、その要素の Focusable および IsVisible を true に設定する必要があります。初期フォーカスを設定する場所は、Loaded イベント ハンドラ内にすることをお勧めします。Dispatcher コールバックは、Invoke または BeginInvoke を呼び出して使用することもできます。

論理フォーカス

論理フォーカスとは、フォーカス範囲内の FocusManager.FocusedElement を意味します。フォーカス範囲とは、その範囲内の FocusedElement を追跡する要素です。キーボード フォーカスがフォーカス範囲を離れると、フォーカスがある要素はキーボード フォーカスを失いますが、論理フォーカスは引き続き保持します。キーボード フォーカスがフォーカス範囲に戻ると、フォーカスがある要素はキーボード フォーカスを得ます。これにより、キーボード フォーカスが複数のフォーカス範囲間で変更されても、フォーカスがフォーカス範囲に戻ると、そのフォーカス範囲内のフォーカスがある要素はキーボード フォーカスを取り戻すことができます。

アプリケーションでは、複数の要素が論理フォーカスを持つことがありますが、特定のフォーカス範囲で論理フォーカスを持つ要素は 1 つだけに限られます。

キーボード フォーカスを持つ要素は、その要素が属するフォーカス範囲の論理フォーカスを持ちます。

Extensible Application Markup Language (XAML) では、FocusManager の添付プロパティ IsFocusScope を true に設定して、要素をフォーカス範囲にすることができます。コードでは、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);

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);

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

KeyboardNavigation クラスは、ナビゲーション キーのいずれかが押されたときに、既定のキーボード フォーカスのナビゲーションを実装します。ナビゲーション キーとは、Tab、Shift + Tab、Ctrl + Tab、Ctrl + Shift + Tab、上方向、下方向、左方向、および右方向の各キーを指します。

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

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

<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);

プログラムによるフォーカスのナビゲーション

フォーカスを操作するための追加の 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);
}

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

フォーカス イベント

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

要素がキーボード フォーカスを得ると、GotKeyboardFocus が発生します。要素がキーボード フォーカスを失うと、LostKeyboardFocus が発生します。PreviewGotKeyboardFocus イベントまたは PreviewLostKeyboardFocusEvent イベントが処理され、Handled が true に設定されると、フォーカスは変更されなくなります。

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();
    }
}

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();
    }
}

論理フォーカスに関連するイベントには、GotFocus および LostFocus があります。これらのイベントは、FocusManager で添付イベントとして定義されますが、FocusManager は CLR イベント ラッパーを公開しません。UIElement および ContentElement は、これらのイベントをより便利に公開しています。

参照

概念

入力の概要

基本要素の概要

参照

FocusManager

UIElement

ContentElement