Not
Åtkomst till denna sida kräver auktorisation. Du kan prova att logga in eller byta katalog.
Åtkomst till denna sida kräver auktorisation. Du kan prova att byta katalog.
Om du vill flytta fokus programmatiskt i ditt Windows-program kan du använda metoden FocusManager.TryMoveFocus eller metoden FindNextElement .
TryMoveFocus försöker ändra fokus från elementet med fokus till nästa fokuserbara element i den angivna riktningen, medan FindNextElement hämtar elementet (som ett DependencyObject) som kommer att få fokus baserat på den angivna navigeringsriktningen (endast riktningsnavigering, kan inte användas för att emulera tabbnavigering).
Anmärkning
Vi rekommenderar att du använder metoden FindNextElement i stället för FindNextFocusableElement eftersom FindNextFocusableElement hämtar ett UIElement, som returnerar null om nästa fokuserbara element inte är ett UIElement (till exempel ett hyperlänkobjekt).
Hitta en fokuskandidat inom ett omfång
Du kan anpassa fokusnavigeringsbeteendet för både TryMoveFocus och FindNextElement, inklusive sökning efter nästa fokuskandidat i ett specifikt gränssnittsträd eller exkludera specifika element från övervägande.
I det här exemplet används ett TicTacToe-spel för att demonstrera metoderna TryMoveFocus och FindNextElement .
<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);
}
}
Använd FindNextElementOptions för att ytterligare anpassa hur fokuskandidater identifieras. Det här objektet innehåller följande egenskaper:
- SearchRoot – Begränsa sökomfånget för fokusnavigeringskandidater till barnobjekt till denna DependencyObject. Null anger att sökningen ska startas från roten i det visuella trädet.
Viktigt!
Om en eller flera transformationer tillämpas på de underordnade till SearchRoot som placerar dem utanför det riktade området betraktas dessa element fortfarande som kandidater.
- ExclusionRect – Fokusnavigeringskandidater identifieras med hjälp av en "fiktiv" avgränsningsrektangel där alla överlappande objekt undantas från navigeringsfokus. Den här rektangeln används endast för beräkningar och läggs aldrig till i det visuella trädet.
- HintRect – Fokusnavigeringskandidater identifieras med hjälp av en "fiktiv" rektangel som identifierar de element som mest sannolikt kommer att få fokus. Den här rektangeln används endast för beräkningar och läggs aldrig till i det visuella trädet.
- XYFocusNavigationStrategyOverride – fokusnavigeringsstrategin som används för att identifiera det bästa kandidatelementet för att få fokus.
Följande bild illustrerar några av dessa begrepp.
När element B har fokus identifierar FindNextElement mig som fokuskandidat när du navigerar till höger. Orsakerna till detta är:
- På grund av HintRect på A är startreferensen A, inte B
- C är inte en kandidat eftersom MyPanel har angetts som SearchRoot
- F är inte en kandidat eftersom ExclusionRect överlappar den
Beteende för anpassad fokusnavigering med hjälp av navigeringstips
Navigeringsfokushändelser
NoFocusCandidateFound-händelse
Händelsen UIElement.NoFocusCandidateFound utlöses när fliken eller piltangenterna trycks ned och det inte finns någon fokuskandidat i den angivna riktningen. Den här händelsen utlöses inte för TryMoveFocus.
Eftersom det här är en dirigerad händelse bubblar den från det fokuserade elementet uppåt genom efterföljande överordnade objekt till objektträdets rot. På så sätt kan du hantera händelsen när det är lämpligt.
Här visar vi hur ett rutnät öppnar en SplitView när användaren försöker flytta fokus till vänster om den vänster mest fokuserbara kontrollen (se Designa för Xbox och 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;
}
}
Händelser för GotFocus och LostFocus
Händelserna UIElement.GotFocus och UIElement.LostFocus utlöses när ett element fokuserar eller förlorar fokus. Den här händelsen utlöses inte för TryMoveFocus.
Eftersom det här är routade händelser bubblar de från det fokuserade elementet uppåt genom efterföljande överordnade objekt till objektträdets rot. På så sätt kan du hantera händelsen när det är lämpligt.
GettingFocus- och LosingFocus-händelser
Händelserna UIElement.GettingFocus och UIElement.LosingFocus utlöses före respektive UIElement.GotFocus - och UIElement.LostFocus-händelser .
Eftersom det här är routade händelser bubblar de från det fokuserade elementet uppåt genom efterföljande överordnade objekt till objektträdets rot. Eftersom detta händer innan en fokusändring sker kan du omdirigera eller avbryta fokusändringen.
GettingFocus och LosingFocus är synkrona händelser så fokus flyttas inte medan dessa händelser bubblar. GotFocus och LostFocus är dock asynkrona händelser, vilket innebär att det inte finns någon garanti för att fokus inte flyttas igen innan hanteraren körs.
Om fokus flyttas genom ett anrop till Control.Focus aktiveras GettingFocus under anropet, medan GotFocus aktiveras efter anropet.
Fokusnavigeringsmålet kan ändras under händelserna GettingFocus och LosingFocus (innan fokus flyttas) via egenskapen GettingFocusEventArgs.NewFocusedElement . Även om målet ändras bubblar händelsen fortfarande och målet kan ändras igen.
För att undvika återträdbarhetsproblem utlöses ett undantag om du försöker flytta fokus genom att använda TryMoveFocus eller Control.Focus när dessa händelser bubblar.
Dessa händelser utlöses oavsett orsaken till att fokus flyttas (inklusive fliknavigering, riktningsnavigering och programmeringsnavigering).
Här är körningsordningen för fokushändelserna:
- LosingFocus Om fokus återställs till det förlorande fokuselementet eller om TryCancel lyckas utlöses inga ytterligare händelser.
- GettingFocus Om fokus återställs till det förlorande fokuselementet eller om TryCancel lyckas utlöses inga ytterligare händelser.
- LostFocus
- GotFocus
Följande bild visar hur XYFocus väljer B4 som kandidat när du flyttar till höger från A. B4 utlöser sedan händelsen GettingFocus där ListView har möjlighet att omtilldela fokus till B3.
Ändra fokusnavigeringsmål för Händelsen GettingFocus
Här visar vi hur du hanterar händelsen GettingFocus och omdirigerar fokus.
<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;
}
}
}
Här visar vi hur du hanterar händelsen LosingFocus för en kommandorad och anger fokus när menyn stängs.
<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;
}
}
}
Hitta det första och sista fokuserbara elementet
Metoderna FocusManager.FindFirstFocusableElement och FocusManager.FindLastFocusableElement flyttar fokus till det första eller sista fokuserbara elementet inom omfånget för ett objekt (elementträdet i ett UIElement eller textträdet i ett TextElement). Omfånget anges i anropet (om argumentet är null är omfånget det aktuella fönstret).
Om inga fokuskandidater kan identifieras i omfånget returneras null.
Här visar vi hur du anger att knapparna i en kommandorad har ett omslutande riktningsbeteende (se Tangentbordsinteraktioner).
<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;
}
}
}
Relaterade artiklar
Windows developer