Freigeben über


Fokusübersicht

In WPF gibt es zwei Hauptkonzepte, die sich auf den Fokus beziehen: Tastaturfokus und logischer Fokus. Der Tastaturfokus bezieht sich auf das Element, das Tastatureingaben empfängt, und der logische Fokus bezieht sich auf das Element in einem Fokusbereich, das den Fokus hat. Diese Konzepte werden in dieser Übersicht ausführlich erläutert. Das Verständnis des Unterschieds in diesen Konzepten ist wichtig für die Erstellung komplexer Anwendungen mit mehreren Regionen, in denen der Fokus abgerufen werden kann.

Die Hauptklassen, die an der Fokusverwaltung teilnehmen, sind die Klassen Keyboard, FocusManager und die Basiselementklassen wie UIElement und ContentElement. Weitere Informationen zu den Basiselementen finden Sie in der Übersicht über Basiselemente.

Die Keyboard Klasse befasst sich in erster Linie mit dem Tastaturfokus, und die FocusManager Klasse befasst sich hauptsächlich mit dem logischen Fokus. Dies ist jedoch keine absolute Unterscheidung. Ein Element mit Tastaturfokus hat auch logischen Fokus, aber ein Element, das den logischen Fokus hat, hat nicht unbedingt den Tastaturfokus. Dies wird ersichtlich, wenn Sie die Keyboard Klasse verwenden, um das Element festzulegen, das den Tastaturfokus besitzt, da es auch den logischen Fokus auf das Element legt.

Tastaturfokus

Der Tastaturfokus bezieht sich auf das Element, das derzeit Tastatureingaben empfängt. Es kann nur ein Element auf dem gesamten Desktop vorhanden sein, das den Tastaturfokus besitzt. In WPF wird das Element, das den Tastaturfokus besitzt, auf IsKeyboardFocused gesetzt. Die statische Eigenschaft FocusedElement der Keyboard Klasse ruft das Element ab, das derzeit den Tastaturfokus besitzt.

Damit ein Element den Tastaturfokus erhält, müssen die Focusable und die IsVisible Eigenschaften der Basiselemente auf true festgelegt werden. Einige Klassen, wie die Panel Basisklasse, haben Focusable standardmäßig auf false gesetzt. Daher müssen Sie Focusable auf true setzen, wenn ein solches Element in der Lage sein soll, den Tastaturfokus zu erhalten.

Der Tastaturfokus kann über die Benutzerinteraktion mit der Benutzeroberfläche abgerufen werden, z. B. durch Hervorheben eines Elements mit der Tabulatortaste oder indem man mit der Maus auf bestimmte Elemente klickt. Der Tastaturfokus kann auch programmgesteuert mithilfe der Focus Methode für die Keyboard Klasse abgerufen werden. Die Focus Methode versucht, dem angegebenen Element den Tastaturfokus zuzuweisen. Das zurückgegebene Element ist das Element, das den Tastaturfokus besitzt. Dies kann ein anderes Element sein als angefordert, wenn entweder das alte oder das neue Fokusobjekt die Anforderung blockieren.

Im folgenden Beispiel wird die Focus Methode verwendet, um den Tastaturfokus auf ein 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

Die IsKeyboardFocused Eigenschaft der Basiselementklassen ruft einen Wert ab, der angibt, ob das Element den Tastaturfokus hat. Die IsKeyboardFocusWithin Eigenschaft der Basiselementklassen ruft einen Wert ab, der angibt, ob das Element oder eines seiner visuellen untergeordneten Elemente den Tastaturfokus hat.

Wenn Sie den anfänglichen Fokus beim Starten der Anwendung festlegen, muss sich das Element, das den Fokus erhält, innerhalb der visuellen Struktur des anfänglichen Fensters befinden, das von der Anwendung geladen wird, und das Element muss Focusable und IsVisible auf true gesetzt sein. Die empfohlene Stelle, um den anfänglichen Fokus festzulegen, ist im Loaded Ereignishandler. Ein Dispatcher Rückruf kann auch durch Aufrufen von Invoke oder BeginInvoke verwendet werden.

Logischer Fokus

Der logische Fokus bezieht sich auf den FocusManager.FocusedElement in einem Fokusbereich. Ein Fokusbereich ist ein Element, das den Überblick über den FocusedElement innerhalb seines Bereichs behält. Wenn der Tastaturfokus einen Fokusbereich verlässt, verliert das fokussierte Element den Tastaturfokus, behält jedoch den logischen Fokus bei. Wenn der Tastaturfokus zum Fokusbereich zurückkehrt, erhält das fokussierte Element den Tastaturfokus. Dadurch kann der Tastaturfokus zwischen mehreren Fokusbereichen geändert werden, stellt jedoch sicher, dass das fokussierte Element im Fokusbereich den Tastaturfokus wieder erhält, wenn der Fokus wieder auf den Fokusbereich zurückgibt.

Es können mehrere Elemente vorhanden sein, die den logischen Fokus in einer Anwendung haben, aber es kann nur ein Element geben, das den logischen Fokus in einem bestimmten Fokusbereich hat.

Ein Element mit Tastaturfokus hat logischen Fokus für den Fokusbereich, zu dem es gehört.

Ein Element kann in Extensible Application Markup Language (XAML) in einen Fokusbereich umgewandelt werden, indem die FocusManager angefügte Eigenschaft IsFocusScope auf truefestgelegt wird. Im Code kann ein Element durch Aufrufen von Aufrufen SetIsFocusScopein einen Fokusbereich umgewandelt werden.

Im folgenden Beispiel wird ein StackPanel zu einem Fokusbereich, indem die angefügte Eigenschaft IsFocusScope 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>
StackPanel focuseScope2 = new StackPanel();
FocusManager.SetIsFocusScope(focuseScope2, true);
Dim focuseScope2 As New StackPanel()
FocusManager.SetIsFocusScope(focuseScope2, True)

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

Klassen in WPF, die standardmäßig Fokusbereiche sind, sind Window, , MenuItem, ToolBarund ContextMenu.

GetFocusedElement ruft das fokussierte Element für den angegebenen Fokusbereich ab. SetFocusedElement legt das fokussierte Element im angegebenen Fokusbereich fest. SetFocusedElement wird in der Regel verwendet, um das anfängliche fokussierte Element festzulegen.

Im folgenden Beispiel wird das fokussierte Element auf einem Fokusbereich festgelegt und das fokussierte Element eines Fokusbereichs abgerufen.

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

Tastaturnavigation

Die KeyboardNavigation Klasse ist für die Implementierung der Standardmäßigen Tastaturfokusnavigation verantwortlich, wenn eine der Navigationstasten gedrückt wird. Die Navigationstasten sind: TAB, UMSCHALT+TAB, STRG+TAB, STRG+UMSCHALT+TAB, UPARROW, DOWNARROW, LEFTARROW und RIGHTARROW.

Das Navigationsverhalten eines Navigationscontainers kann geändert werden, indem die angefügten KeyboardNavigation Eigenschaften TabNavigationfestgelegt werden, ControlTabNavigationund DirectionalNavigation. Diese Eigenschaften sind vom Typ KeyboardNavigationMode und die möglichen Werte sind Continue, , Local, Contained, , Cycle, und OnceNone. Der Standardwert lautet Continue, was bedeutet, dass das Element kein Navigationscontainer ist.

Im folgenden Beispiel wird eine Menu mit einer Reihe von MenuItem Objekten erstellt. Die TabNavigation angefügte Eigenschaft wird Cycle für die Menu. Wenn der Fokus mithilfe der Tabulatortaste innerhalb des MenuElements geändert wird, wechselt der Fokus von jedem Element, und wenn das letzte Element erreicht wird, 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>
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)

Zusätzliche APIs, die mit Fokus arbeiten, sind MoveFocus und PredictFocus.

MoveFocus ändert den Fokus auf das nächste Element in der Anwendung. A TraversalRequest wird verwendet, um die Richtung anzugeben. Der an FocusNavigationDirection übergebene MoveFocus gibt die verschiedenen Richtungen an, in die der Fokus verschoben werden kann, wie z. B. First, Last, Up und Down.

Im folgenden Beispiel wird MoveFocus verwendet, um das fokussierte Element zu ändern.

// 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 gibt das Objekt zurück, das den Fokus erhält, wenn der Fokus geändert werden soll. Derzeit werden nur Up, Down, Left und Right von PredictFocus unterstützt.

Fokusereignisse

Die Ereignisse im Zusammenhang mit dem Tastaturfokus sind PreviewGotKeyboardFocus, GotKeyboardFocus und PreviewLostKeyboardFocus, LostKeyboardFocus. Die Ereignisse werden als angefügte Ereignisse für die Keyboard Klasse definiert, sind aber leichter als gleichwertige Routingereignisse für die Basiselementklassen zugänglich. Weitere Informationen zu Ereignissen finden Sie in der Übersicht über Routingereignisse.

GotKeyboardFocus wird ausgelöst, wenn das Element den Tastaturfokus abruft. 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 GotKeyboardFocus- und LostKeyboardFocus-Ereignishandler an ein TextBox angehängt.

<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 der TextBox den Tastaturfokus erhält, wird die Eigenschaft Background des TextBox in LightBlue geändert.

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

Wenn der TextBox Tastaturfokus verloren geht, wird die Background-Eigenschaft von TextBox wieder auf Weiß geändert.

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

Die Ereignisse im Zusammenhang mit logischem Fokus sind GotFocus und LostFocus. Diese Ereignisse werden für die FocusManager als angefügten Ereignisse definiert, aber die FocusManager CLR-Ereigniswrapper werden nicht verfügbar gemacht. UIElement und ContentElement machen diese Ereignisse bequemer verfügbar.

Siehe auch