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. Der logische Fokus bezieht sich auf das Element innerhalb eines Fokusbereichs, 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 Keyboard Klasse, die FocusManager Klasse und die Basiselementklassen, z. B. UIElement und ContentElement. Weitere Informationen zu den Basiselementen finden Sie unter Base Elements Overview.
Die Keyboard Klasse befasst sich in erster Linie mit Tastaturfokus, und die FocusManager befasst sich in erster Linie mit logischem Fokus, aber das ist keine absolute Unterscheidung. Ein Element, das den Tastaturfokus hat, hat auch den logischen Fokus, aber ein Element mit logischem Fokus hat nicht unbedingt den Tastaturfokus. Dies wird ersichtlich, wenn Sie die Klasse Keyboard verwenden, um das Element festzulegen, das den Tastaturfokus besitzt, denn dadurch wird auch der logische Fokus auf das Element festgelegt.
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 hat, von IsKeyboardFocused auf true
gesetzt. Die statische Eigenschaft FocusedElement der Klasse Keyboard ruft das Element ab, das derzeit den Tastaturfokus hat.
Damit ein Element den Tastaturfokus erhält, müssen die Eigenschaften Focusable und IsVisible für die Basiselemente auf true
festgelegt werden. Einige Klassen, z. B. die Panel Basisklasse, haben standardmäßig Focusable auf false
festgelegt; Daher müssen Sie Focusable auf true
festlegen, wenn ein solches Element in der Lage sein soll, den Tastaturfokus zu erhalten.
Der Tastaturfokus kann durch Benutzerinteraktion mit der Benutzeroberfläche erlangt werden, z. B. durch Navigieren mit der Tabulatortaste zu einem Element oder durch Klicken mit der Maus auf bestimmte Elemente. Der Tastaturfokus kann auch programmgesteuert mithilfe der Focus-Methode in der Keyboard-Klasse abgerufen werden. Die Methode Focus versucht, dem angegebenen Element den Tastaturfokus zu verleihen. 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 eine Buttonfestzulegen.
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 erhält einen Wert, 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.
Beim Start der Anwendung muss das Element, das den Fokus erhält, sich in der visuellen Struktur des anfänglichen Fensters befinden, das von der Anwendung geladen wird. Zudem müssen die Eigenschaften Focusable und IsVisible auf true
gesetzt sein. Die empfohlene Stelle zum Festlegen des anfänglichen Fokus befindet sich im Loaded-Ereignishandler. Ein Dispatcher Rückruf kann auch durch Aufrufen von Invoke oder BeginInvokeverwendet werden.
Logischer Fokus
Der logische Fokus bezieht sich auf die FocusManager.FocusedElement in einem Fokusbereich. Ein Fokusbereich ist ein Element, das den FocusedElement innerhalb seines Bereichs nachverfolgt. 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 und stellt sicher, dass das fokussierte Element im Fokusbereich den Tastaturfokus wieder erhält, wenn der Fokus zum Fokusbereich zurückkehrt.
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 angehängte Eigenschaft FocusManagerIsFocusScope auf true
festgelegt wird. Im Code kann ein Element in einen Fokusbereich umgewandelt werden, indem SetIsFocusScopeaufgerufen wird.
Im folgenden Beispiel wird ein StackPanel in einen Fokusbereich umgewandelt, 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 TabNavigation, ControlTabNavigationund DirectionalNavigationfestgelegt werden. Diese Eigenschaften sind vom Typ KeyboardNavigationMode und die möglichen Werte sind Continue, Local, Contained, Cycle, Onceund None. Der Standardwert ist Continue, was bedeutet, dass das Element kein Navigationscontainer ist.
Im folgenden Beispiel wird eine Menu mit einer Reihe von MenuItem Objekten erstellt. Die angefügte eigenschaft TabNavigation wird für die Menuauf Cycle festgelegt. Wenn der Fokus mithilfe der TAB-TASTE innerhalb der Menugeändert wird, bewegt sich der Fokus von Element zu Element und wenn das letzte Element erreicht ist, kehrt er 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)
Programmgesteuertes Navigieren des Fokus
Zusätzliche API für die Arbeit mit Fokus sind MoveFocus und PredictFocus.
MoveFocus ändert den Fokus auf das nächste Element in der Anwendung. Ein TraversalRequest wird verwendet, um die Richtung anzugeben. Die an MoveFocus übergebene FocusNavigationDirection 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, Leftund Right von PredictFocusunterstützt.
Fokusereignisse
Die Ereignisse bezüglich Tastaturfokus sind PreviewGotKeyboardFocus, GotKeyboardFocus und PreviewLostKeyboardFocus, LostKeyboardFocus. Die Ereignisse werden als angefügte Ereignisse für die Keyboard-Klasse definiert, sind jedoch leichter als gleichwertige geroutete Ereignisse in den Basiselementklassen zugänglich. Weitere Informationen zu Ereignissen finden Sie in der Ü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 GotKeyboardFocus und LostKeyboardFocus Ereignishandler an eine TextBoxangefü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 TextBox den Tastaturfokus erhält, wird die Eigenschaft von Background des TextBox in LightBluegeä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 die TextBox den Tastaturfokus verliert, wird die Eigenschaft Background des TextBox wieder auf Weiß gesetzt.
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ügte Ereignisse definiert, aber die FocusManager macht keine CLR-Ereigniswrapper verfügbar. UIElement und ContentElement machen diese Ereignisse leichter zugänglich.
Siehe auch
.NET Desktop feedback