Fokus - Übersicht
Aktualisiert: November 2007
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 Benutzeroberfläche 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 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 mit einer PresentationSource verknüpft sein, und Focusable sowie IsVisible müssen für das Element 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>
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
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>
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. Den vollständigen Quellcode für dieses Beispiel finden Sie unter Beispiel für das programmgesteuerte Ändern des Fokus.
// 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 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 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.