Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Um den Fokus programmgesteuert in Ihrer Windows-Anwendung zu verschieben, können Sie entweder die FocusManager.TryMoveFocus-Methode oder die FindNextElement-Methode verwenden.
TryMoveFocus versucht, den Fokus vom Element mit Fokus auf das nächste fokussierbare Element in der angegebenen Richtung zu ändern, während FindNextElement das Element (als DependencyObject) abruft, das den Fokus basierend auf der angegebenen Navigationsrichtung erhält (nur direktionale Navigation, kann nicht zum Emulieren der Registerkartennavigation verwendet werden).
Hinweis
Es wird empfohlen, die FindNextElement-Methode anstelle von FindNextFocusableElement zu verwenden, da FindNextFocusableElement ein UIElement abruft, das NULL zurückgibt, wenn das nächste fokussierbare Element kein UIElement ist (z. B. ein Hyperlink-Objekt).
Suchen eines Fokuskandidaten innerhalb eines Bereichs
Sie können das Fokusnavigationsverhalten sowohl für TryMoveFocus als auch für FindNextElement anpassen, einschließlich der Suche nach dem nächsten Fokuskandidaten in einer bestimmten UI-Struktur oder ausschließen von bestimmten Elementen.
In diesem Beispiel wird ein TicTacToe-Spiel verwendet, um die Methoden TryMoveFocus und FindNextElement zu veranschaulichen.
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center"
HorizontalAlignment="Center" >
<Button Content="Start Game" />
<Button Content="Undo Movement" />
<Grid x:Name="TicTacToeGrid" KeyDown="OnKeyDown">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="50" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<myControls:TicTacToeCell
Grid.Column="0" Grid.Row="0"
x:Name="Cell00" />
<myControls:TicTacToeCell
Grid.Column="1" Grid.Row="0"
x:Name="Cell10"/>
<myControls:TicTacToeCell
Grid.Column="2" Grid.Row="0"
x:Name="Cell20"/>
<myControls:TicTacToeCell
Grid.Column="0" Grid.Row="1"
x:Name="Cell01"/>
<myControls:TicTacToeCell
Grid.Column="1" Grid.Row="1"
x:Name="Cell11"/>
<myControls:TicTacToeCell
Grid.Column="2" Grid.Row="1"
x:Name="Cell21"/>
<myControls:TicTacToeCell
Grid.Column="0" Grid.Row="2"
x:Name="Cell02"/>
<myControls:TicTacToeCell
Grid.Column="1" Grid.Row="2"
x:Name="Cell22"/>
<myControls:TicTacToeCell
Grid.Column="2" Grid.Row="2"
x:Name="Cell32"/>
</Grid>
</StackPanel>
private void OnKeyDown(object sender, KeyRoutedEventArgs e)
{
DependencyObject candidate = null;
var options = new FindNextElementOptions ()
{
SearchRoot = TicTacToeGrid,
XYFocusNavigationStrategyOverride = XYFocusNavigationStrategyOverride.Projection
};
switch (e.Key)
{
case Windows.System.VirtualKey.Up:
candidate =
FocusManager.FindNextElement(
FocusNavigationDirection.Up, options);
break;
case Windows.System.VirtualKey.Down:
candidate =
FocusManager.FindNextElement(
FocusNavigationDirection.Down, options);
break;
case Windows.System.VirtualKey.Left:
candidate = FocusManager.FindNextElement(
FocusNavigationDirection.Left, options);
break;
case Windows.System.VirtualKey.Right:
candidate =
FocusManager.FindNextElement(
FocusNavigationDirection.Right, options);
break;
}
// Also consider whether candidate is a Hyperlink, WebView, or TextBlock.
if (candidate != null && candidate is Control)
{
(candidate as Control).Focus(FocusState.Keyboard);
}
}
Verwenden Sie FindNextElementOptions , um die Identifizierung von Fokuskandidaten weiter anzupassen. Dieses Objekt stellt die folgenden Eigenschaften bereit:
- SearchRoot – Begrenzen Sie die Suche nach Fokusnavigationskandidaten auf die untergeordneten Elemente dieses Abhängigkeitsobjekts. Null gibt an, dass die Suche vom Stamm des visuellen Baums aus gestartet wird.
Von Bedeutung
Wenn eine oder mehrere Transformationen auf die Nachfolger von SearchRoot angewendet werden, die sie außerhalb des direktionalen Bereichs platzieren, werden diese Elemente weiterhin als Kandidaten betrachtet.
- ExclusionRect – Fokusnavigationskandidaten werden mithilfe eines "fiktiven" Begrenzungsrechtecks identifiziert, in dem alle überlappenden Objekte vom Navigationsfokus ausgeschlossen werden. Dieses Rechteck wird nur für Berechnungen verwendet und der visuellen Struktur nie hinzugefügt.
- HintRect – Fokusnavigationskandidaten werden mithilfe eines "fiktiven" Begrenzungsrechtecks identifiziert, das die Elemente identifiziert, die am wahrscheinlichsten den Fokus erhalten. Dieses Rechteck wird nur für Berechnungen verwendet und der visuellen Struktur nie hinzugefügt.
- XYFocusNavigationStrategyOverride – Die Fokusnavigationsstrategie, die verwendet wird, um das beste Kandidatenelement zu identifizieren, das den Fokus erhalten soll.
Die folgende Abbildung veranschaulicht einige dieser Konzepte.
Wenn Element B den Fokus hat, identifiziert FindNextElement beim Navigieren nach rechts I als Fokuskandidaten. Die Gründe hierfür sind:
- Aufgrund des HintRect für A lautet der Anfangsverweis A, nicht B
- C ist kein Kandidat, da MyPanel als SearchRoot angegeben wurde
- F ist kein Kandidat, da der ExclusionRect ihn überlappt.
Benutzerdefiniertes Fokusnavigationsverhalten mithilfe von Navigationshinweisen
Navigationsfokusereignisse
NoFocusCandidateFound-Ereignis
Das UIElement.NoFocusCandidateFound-Ereignis wird ausgelöst, wenn die Tab- oder Pfeiltasten gedrückt werden und es keinen Fokuskandidaten in der angegebenen Richtung gibt. Dieses Ereignis wird für TryMoveFocus nicht ausgelöst.
Da es sich um ein Routed Event handelt, blubbert es vom fokussierten Element über aufeinanderfolgende übergeordnete Objekte bis zum Stamm des Objektbaums. Auf diese Weise können Sie das Ereignis dort behandeln, wo es angemessen ist.
Hier zeigen wir, wie ein Raster eine SplitView öffnet, wenn der Benutzer versucht, den Fokus links vom fokussierbaren Steuerelement zu verschieben (siehe Entwerfen für Xbox und TV).
<Grid NoFocusCandidateFound="OnNoFocusCandidateFound">
...
</Grid>
private void OnNoFocusCandidateFound (
UIElement sender, NoFocusCandidateFoundEventArgs args)
{
if(args.NavigationDirection == FocusNavigationDirection.Left)
{
if(args.InputDevice == FocusInputDeviceKind.Keyboard ||
args.InputDevice == FocusInputDeviceKind.GameController )
{
OpenSplitPaneView();
}
args.Handled = true;
}
}
GotFocus- und LostFocus-Ereignisse
Die Ereignisse "UIElement.GotFocus " und "UIElement.LostFocus " werden ausgelöst, wenn ein Element den Fokus erhält oder den Fokus verliert. Dieses Ereignis wird für TryMoveFocus nicht ausgelöst.
Da dies Routingerignisse sind, steigen sie vom fokussierten Element über aufsteigende übergeordnete Objekte bis zur Wurzel des Objektbaums. Auf diese Weise können Sie das Ereignis dort behandeln, wo es angemessen ist.
GettingFocus- und LosingFocus-Ereignisse
Die Ereignisse "UIElement.GettingFocus " und "UIElement.LosingFocus" werden vor den jeweiligen Ereignissen "UIElement.GotFocus " und "UIElement.LostFocus" ausgelöst.
Da es sich um Routingereignisse handelt, durchlaufen sie das fokussierte Element und steigen durch die nachfolgenden übergeordneten Objekte bis zur Wurzel der Objektstruktur auf. Da dies geschieht, bevor eine Änderung des Fokus stattfindet, können Sie die Fokusänderung umleiten oder abbrechen.
GettingFocus und LosingFocus sind synchrone Ereignisse, sodass der Fokus nicht verschoben wird, während diese Ereignisse bubbling. GotFocus und LostFocus sind jedoch asynchrone Ereignisse, was bedeutet, dass nicht garantiert werden kann, dass der Fokus sich nicht erneut bewegt, bevor der Handler ausgeführt wird.
Wenn der Fokus durch einen Aufruf von Control.Focus wechselt, wird GettingFocus während des Anrufs ausgelöst, während GotFocus nach dem Aufruf ausgelöst wird.
Das Fokusnavigationsziel kann während der GettingFocus - und LosingFocus-Ereignisse (bevor der Fokus verschoben wird) über die GettingFocusEventArgs.NewFocusedElement-Eigenschaft geändert werden. Selbst wenn das Ziel geändert wird, wird das Ereignis weiterhin weitergeleitet und das Ziel kann erneut geändert werden.
Um Reentrancy-Probleme zu vermeiden, wird eine Ausnahme ausgelöst, wenn Sie versuchen, den Fokus (mithilfe von TryMoveFocus oder Control.Focus) zu verschieben, während diese Ereignisse bubbling.
Diese Ereignisse werden unabhängig vom Grund für die Verschiebung des Fokus ausgelöst (einschließlich Tab-Navigation, direktionaler Navigation und programmgesteuerter Navigation).
Dies ist die Reihenfolge der Ausführung für die Fokusereignisse:
- LosingFocus Wenn der Fokus wieder auf das verlorene Fokuselement zurückgesetzt wird oder TryCancel erfolgreich ist, werden keine weiteren Ereignisse ausgelöst.
- GettingFocus Wenn der Fokus wieder auf das verlorene Fokuselement zurückgesetzt wird oder TryCancel erfolgreich ist, werden keine weiteren Ereignisse ausgelöst.
- LostFocus
- GotFocus
Die folgende Abbildung zeigt, wie der XYFocus bei einem Wechsel von A nach rechts B4 als Kandidat auswählt. B4 löst dann das GettingFocus-Ereignis aus, bei dem das ListView die Möglichkeit hat, den Fokus erneut auf B3 zuzuweisen.
Ändern des Fokusnavigationsziels für das GettingFocus-Ereignis
Hier erfahren Sie, wie Sie das GettingFocus-Ereignis behandeln und den Fokus umleiten.
<StackPanel Orientation="Horizontal">
<Button Content="A" />
<ListView x:Name="MyListView" SelectedIndex="2" GettingFocus="OnGettingFocus">
<ListViewItem>LV1</ListViewItem>
<ListViewItem>LV2</ListViewItem>
<ListViewItem>LV3</ListViewItem>
<ListViewItem>LV4</ListViewItem>
<ListViewItem>LV5</ListViewItem>
</ListView>
</StackPanel>
private void OnGettingFocus(UIElement sender, GettingFocusEventArgs args)
{
//Redirect the focus only when the focus comes from outside of the ListView.
// move the focus to the selected item
if (MyListView.SelectedIndex != -1 &&
IsNotAChildOf(MyListView, args.OldFocusedElement))
{
var selectedContainer =
MyListView.ContainerFromItem(MyListView.SelectedItem);
if (args.FocusState ==
FocusState.Keyboard &&
args.NewFocusedElement != selectedContainer)
{
args.TryRedirect(
MyListView.ContainerFromItem(MyListView.SelectedItem));
args.Handled = true;
}
}
}
Hier zeigen wir, wie Sie das LosingFocus-Ereignis für eine CommandBar behandeln und den Fokus festlegen, wenn das Menü geschlossen wird.
<CommandBar x:Name="MyCommandBar" LosingFocus="OnLosingFocus">
<AppBarButton Icon="Back" Label="Back" />
<AppBarButton Icon="Stop" Label="Stop" />
<AppBarButton Icon="Play" Label="Play" />
<AppBarButton Icon="Forward" Label="Forward" />
<CommandBar.SecondaryCommands>
<AppBarButton Icon="Like" Label="Like" />
<AppBarButton Icon="Share" Label="Share" />
</CommandBar.SecondaryCommands>
</CommandBar>
private void OnLosingFocus(UIElement sender, LosingFocusEventArgs args)
{
if (MyCommandBar.IsOpen == true &&
IsNotAChildOf(MyCommandBar, args.NewFocusedElement))
{
if (args.TryCancel())
{
args.Handled = true;
}
}
}
Suchen des ersten und letzten fokussierbaren Elements
Die Methoden FocusManager.FindFirstFocusableElement und FocusManager.FindLastFocusableElement verschieben den Fokus auf das erste oder letzte fokussierbare Element innerhalb des Bereichs eines Objekts (die Elementstruktur eines UIElements oder die Textstruktur eines TextElements). Der Bereich wird im Aufruf angegeben (wenn das Argument null ist, ist der Bereich das aktuelle Fenster).
Wenn im Bereich keine Fokuskandidaten identifiziert werden können, wird NULL zurückgegeben.
Hier wird gezeigt, wie Sie angeben, dass die Schaltflächen einer CommandBar ein umbrechendes direktionales Verhalten aufweisen (siehe Tastaturinteraktionen).
<CommandBar x:Name="MyCommandBar" LosingFocus="OnLosingFocus">
<AppBarButton Icon="Back" Label="Back" />
<AppBarButton Icon="Stop" Label="Stop" />
<AppBarButton Icon="Play" Label="Play" />
<AppBarButton Icon="Forward" Label="Forward" />
<CommandBar.SecondaryCommands>
<AppBarButton Icon="Like" Label="Like" />
<AppBarButton Icon="ReShare" Label="Share" />
</CommandBar.SecondaryCommands>
</CommandBar>
private void OnLosingFocus(UIElement sender, LosingFocusEventArgs args)
{
if (IsNotAChildOf(MyCommandBar, args.NewFocussedElement))
{
DependencyObject candidate = null;
if (args.Direction == FocusNavigationDirection.Left)
{
candidate = FocusManager.FindLastFocusableElement(MyCommandBar);
}
else if (args.Direction == FocusNavigationDirection.Right)
{
candidate = FocusManager.FindFirstFocusableElement(MyCommandBar);
}
if (candidate != null)
{
args.NewFocusedElement = candidate;
args.Handled = true;
}
}
}
Verwandte Artikel
Windows developer