Fokus - Übersicht

In WPF gibt es hinsichtlich des Fokus zwei Hauptkonzepte: den Tastaturfokus und den logischen Fokus. Tastaturfokus bezieht sich auf das Element, dem die Tastatureingabe gilt, und logischer Fokus bezieht sich auf das Element mit dem Fokus in einem Fokusbereich. Diese Konzepte werden in dieser Übersicht detailliert besprochen. Die Unterschiede zwischen diesen Konzepten zu kennen ist wichtig, wenn Sie komplexe Anwendungen mit mehreren Bereichen, auf die der Fokus gelegt werden kann, erstellen möchten.

Die hauptsächlich an der Fokusverwaltung beteiligten Klassen sind die Keyboard-Klasse, die FocusManager-Klasse und die Basiselementklassen wie UIElement und ContentElement. Weitere Informationen zu den Basiselementen finden Sie unter Übersicht über Basiselemente.

Die Keyboard-Klasse gilt vornehmlich dem Tastaturfokus und die FocusManager-Klasse dem logischen Fokus, dies ist jedoch keine absolute Unterscheidung. Ein Element mit Tastaturfokus verfügt auch über den logischen Fokus, ein Element mit logischem Fokus weist jedoch nicht unbedingt auch den Tastaturfokus auf. Dies wird deutlich, wenn Sie mit der Keyboard-Klasse das Element mit dem Tastaturfokus festlegen, da das Element hierdurch auch den logischen Fokus erhält.

Dieses Thema enthält folgende Abschnitte.

  • Tastaturfokus
  • Logischer Fokus
  • Tastaturnavigation
  • Programmgesteuerte Fokusnavigation
  • Fokusereignisse
  • Verwandte Abschnitte

Tastaturfokus

Tastaturfokus bezieht sich auf das Element, dem die derzeitige Tastatureingabe gilt. Auf dem gesamten Desktop kann es nur ein Element mit Tastaturfokus geben. In WPF weist IsKeyboardFocused für das Element, das den Tastaturfokus besitzt, den Wert true auf. Die statische FocusedElement-Eigenschaft in der Keyboard-Klasse ruft das Element ab, auf dem gerade der Tastaturfokus liegt.

Damit ein Element den Tastaturfokus erhalten kann, müssen die Focusable-Eigenschaft und die IsVisible-Eigenschaft in den Basiselementen auf true festgelegt sein. Bei einigen Klassen wie der Panel-Basisklasse ist Focusable standardmäßig auf false festgelegt. Daher müssen Sie Focusable auf true festlegen, wenn diese Elemente in der Lage sein sollen, den Tastaturfokus zu erhalten.

Der Tastaturfokus kann durch eine Interaktion des Benutzers mit der UI auf ein Element gelegt werden, zum Beispiel, wenn der Benutzer mit der TAB-TASTE zu einem Element springt oder mit der Maustaste darauf klickt. Der Tastaturfokus kann auch programmgesteuert über die Focus-Methode in der Keyboard-Klasse bezogen werden. Die Focus-Methode versucht, den Tastaturfokus auf das angegebene Element zu legen. Das zurückgegebene Element ist das Element mit dem Tastaturfokus. Dies kann ein anderes als das gewünschte Element sein, falls das alte oder das neue Fokusobjekt die Anforderung blockiert.

Im folgenden Beispiel wird mit der Focus-Methode der Tastaturfokus auf einen Button gelegt.

        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
private void OnLoaded(object sender, RoutedEventArgs e)
{
    // Sets keyboard focus on the first Button in the sample.
    Keyboard.Focus(firstButton);
}

Die IsKeyboardFocused-Eigenschaft in den Basiselementklassen ruft einen Wert ab, der anzeigt, ob der Tastaturfokus auf dem Element liegt. Die IsKeyboardFocusWithin-Eigenschaft in den Basiselementklassen ruft einen Wert ab, der anzeigt, ob der Tastaturfokus auf dem Element oder einem seiner sichtbaren untergeordneten Elemente liegt.

Das Element, das beim Start der Anwendung zuerst den Fokus erhalten soll, muss sich in der visuellen Struktur des ersten von der Anwendung geladenen Fensters befinden, und für das Element müssen Focusable und IsVisible auf true festgelegt sein. Am besten platzieren Sie den Anfangsfokus im Loaded-Ereignishandler. Sie können auch einen Dispatcher-Rückruf verwenden, indem Sie Invoke oder BeginInvoke aufrufen.

Logischer Fokus

Der logische Fokus bezieht sich auf das FocusManager.FocusedElement in einem Fokusbereich. Bei einem Fokusbereich handelt es sich um ein Element, das das FocusedElement innerhalb seines Bereichs verfolgt. Wenn der Tastaturfokus einen Fokusbereich verlässt, verliert das fokussierte Element den Tastaturfokus, behält jedoch den logischen Fokus. Wenn der Tastaturfokus in den Fokusbereich zurückkehrt, erhält das fokussierte Element wieder den Tastaturfokus. Auf diese Weise kann der Tastaturfokus zwischen verschiedenen Fokusbereichen wechseln, wobei sichergestellt ist, dass das fokussierte Element im Fokusbereich den Tastaturfokus wieder erhält, wenn dieser in diesen Fokusbereich zurückkehrt.

In einer Anwendung kann der logische Fokus auf mehreren Elementen liegen, innerhalb eines bestimmten Fokusbereichs kann jedoch immer nur ein Element den logischen Fokus haben.

Das Element mit dem Tastaturfokus besitzt auch den logischen Fokus innerhalb seines Fokusbereichs.

Sie können ein Element in Extensible Application Markup Language (XAML) zu einem Fokusbereich machen, indem Sie die angefügte FocusManager-Eigenschaft IsFocusScope auf true festlegen. Über Code kann ein Element durch einen Aufruf von SetIsFocusScope in einen Fokusbereich umgewandelt werden.

Im folgenden Beispiel wird ein StackPanel in einen Fokusbereich umgewandelt, indem die angefügte IsFocusScope-Eigenschaft festgelegt wird.

<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>
            Dim focuseScope2 As New StackPanel()
            FocusManager.SetIsFocusScope(focuseScope2, True)
StackPanel focuseScope2 = new StackPanel();
FocusManager.SetIsFocusScope(focuseScope2, true);

GetFocusScope gibt den Fokusbereich für das angegebene Element zurück.

Folgende Klassen in WPF sind standardmäßig Fokusbereiche: Window, MenuItem, ToolBar und ContextMenu

GetFocusedElement ruft das fokussierte Element für den angegebenen Fokusbereich ab. SetFocusedElement legt das Element mit Fokus im angegebenen Fokusbereich fest. SetFocusedElement wird in der Regel verwendet, um das Element mit dem Anfangsfokus festzulegen.

Im folgenden Beispiel wird das fokussierte Element für einen Fokusbereich festgelegt und das Element mit dem Fokus in einem Fokusbereich abgerufen.

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

Tastaturnavigation

Die KeyboardNavigation-Klasse ist dafür verantwortlich, die Standardnavigation für den Tastaturfokus zu implementieren, wenn eine der Navigationstasten gedrückt wird. Die Navigationstasten sind: TAB, UMSCHALT+TAB, STRG+TAB, STRG+UMSCHALT+TAB, NACH-OBEN-TASTE, NACH-UNTEN-TASTE, NACH-LINKS-TASTE und NACH-RECHTS-TASTE.

Das Navigationsverhalten eines Navigationscontainers kann geändert werden, indem Sie die angefügten KeyboardNavigation-Eigenschaften TabNavigation, ControlTabNavigation und DirectionalNavigation festlegen. Diese Eigenschaften haben den Typ KeyboardNavigationMode. Mögliche Werte sind: Continue, Local, Contained, Cycle, Once und None. Der Standardwert ist Continue. Dies bedeutet, dass das Element kein Navigationscontainer ist.

Im folgenden Beispiel wird ein Menu mit verschiedenen MenuItem-Objekten erstellt. Die angefügte TabNavigation-Eigenschaft wird für Menu auf Cycle festgelegt. Eine Fokusänderung über die TAB-TASTE im Menu führt in diesem Fall dazu, dass der Fokus vom jeweiligen Element auf das nächste verschoben wird. Wenn das letzte Element erreicht wurde, kehrt der Fokus zum ersten Element zurück.

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

Programmgesteuerte Fokusnavigation

Bei der Arbeit mit dem Fokus stehen folgende zusätzliche API zur Verfügung: MoveFocus und PredictFocus

MoveFocus legt den Fokus auf das nächste Element in der Anwendung. TraversalRequest wird zur Angabe der Richtung verwendet. Die an MoveFocus übergebene FocusNavigationDirection gibt die verschiedenen Richtungen für die Fokusverschiebung an, zum Beispiel First, Last, Up und Down.

Im folgenden Beispiel wird das fokussierte Element mit MoveFocus gewechselt.

            ' 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
// 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 gibt das Objekt zurück, das den Fokus bei einem Fokuswechsel erhalten würde. Derzeit werden nur Up, Down, Left und Right von PredictFocus unterstützt.

Fokusereignisse

Die Ereignisse für den Tastaturfokus sind PreviewGotKeyboardFocus, GotKeyboardFocus sowie PreviewLostKeyboardFocus und LostKeyboardFocus. Diese Ereignisse sind als angefügte Ereignisse in der Keyboard-Klasse definiert, sie sind jedoch in Form von entsprechenden Routingereignissen in den Basisklassenelementen leichter verfügbar. Weitere Informationen zu Ereignissen finden Sie unter Übersicht über Routingereignisse.

GotKeyboardFocus wird ausgelöst, wenn das Element den Tastaturfokus erhält. LostKeyboardFocus wird ausgelöst, wenn das Element den Tastaturfokus verliert. Wenn das PreviewGotKeyboardFocus-Ereignis oder das PreviewLostKeyboardFocusEvent-Ereignis behandelt wird und Handled auf true festgelegt ist, ändert sich der Fokus nicht.

Im folgenden Beispiel werden ein GotKeyboardFocus-Ereignishandler und ein LostKeyboardFocus-Ereignishandler an eine TextBox angefügt.

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

Wenn die TextBox den Tastaturfokus erhält, wird die Background-Eigenschaft der TextBox auf LightBlue festgelegt.

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

Wenn die TextBox den Tastaturfokus verliert, wird die Background-Eigenschaft der TextBox wieder auf Weiß festgelegt.

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

Die Ereignisse für den logischen Fokus sind: GotFocus und LostFocus. Diese Ereignisse sind im FocusManager als angefügte Ereignisse definiert, der FocusManager macht jedoch keine CLR-Ereigniswrapper verfügbar. UIElement und ContentElement stellen diese Ereignisse auf komfortablere Weise bereit.

Siehe auch

Referenz

FocusManager

UIElement

ContentElement

Konzepte

Übersicht über die Eingabe

Übersicht über Basiselemente