Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Ha programozott módon szeretné áthelyezni a fókuszt a Windows-alkalmazásban, használhatja a FocusManager.TryMoveFocusmetódust vagy a FindNextElement metódust .
A TryMoveFocus megpróbálja módosítani a fókuszt a fókuszt tartalmazó elemről a következő fókuszra a megadott irányban, míg a FindNextElement lekéri azt az elemet ( dependencyObject néven), amely a megadott navigációs irány alapján kapja meg a fókuszt (csak az iránynavigáció nem használható a tabulátornavigáció emulálására).
Megjegyzés:
A FindNextFocusableElement helyett a FindNextElement metódust javasoljuk, mert a FindNextFocusableElement egy UIElement értéket kér le, amely null értéket ad vissza, ha a következő fókuszba helyezhető elem nem UIElement (például hiperhivatkozás-objektum).
Fókuszjelölt keresése hatókörön belül
Testre szabhatja a fókusznavigációs viselkedést a TryMoveFocus és a FindNextElement esetében is, beleértve a következő fókuszjelölt keresését egy adott felhasználói felület fáján belül, vagy kizárhat bizonyos elemeket.
Ez a példa egy TicTacToe-játékot használ a TryMoveFocus és a FindNextElement metódusok bemutatásához.
<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);
}
}
A FindNextElementOptions használatával testre szabhatja a fókuszjelöltek azonosításának módját. Ez az objektum a következő tulajdonságokat biztosítja:
- SearchRoot – A fókusznavigációs jelöltek keresését korlátozza a DependencyObject gyermekeire. A null érték azt jelzi, hogy a keresést a vizualizációfa gyökeréből indítja el.
Fontos
Ha egy vagy több átalakítást alkalmaz a SearchRoot leszármazottaira, amelyek az irányterületen kívül helyezik el őket, ezek az elemek továbbra is jelölteknek minősülnek.
- ExclusionRect – A fókusznavigációs jelöltek egy "fiktív" határolókeret használatával vannak azonosítva, ahol az összes átfedésben lévő objektum ki van zárva a navigációs fókuszból. Ez a téglalap csak számításokhoz használható, és soha nem lesz hozzáadva a vizualizációfához.
- HintRect – A fókusznavigációs jelöltek egy "fiktív" határolókeret használatával vannak azonosítva, amely azonosítja azokat az elemeket, amelyek a legnagyobb valószínűséggel kapják meg a fókuszt. Ez a téglalap csak számításokhoz használható, és soha nem lesz hozzáadva a vizualizációfához.
- XYFocusNavigationStrategyOverride – A fókusznavigációs stratégia, amellyel azonosíthatja a legjobban alkalmas elemet a fókusz fogadásához.
Az alábbi ábrán néhány fogalom látható.
Ha a B elem fókuszban van, a FindNextElement "I"-t azonosítja mint fókuszjelöltet jobbra navigáláskor. Ennek okai a következők:
- Az A-n lévő HintRect miatt a kiindulási hivatkozás az A, nem pedig a B
- A C nem jelölt, mert a MyPanel a SearchRoot-ként lett megadva.
- F nem jelölt, mert a ExclusionRect átfedésben van vele
Egyéni fókusz navigációs viselkedése navigációs tippek használatával
Navigációs fókusz eseményei
NoFocusCandidateFound esemény
A UIElement.NoFocusCandidateFound esemény akkor aktiválódik, ha a lap vagy a nyílbillentyűk lenyomva vannak, és nincs fókuszjelölt a megadott irányban. Ez az esemény nem aktiválódik a TryMoveFocus esetében.
Mivel ez egy irányított esemény, az fókuszált elemtől felfelé áramlik a szülőobjektumokon keresztül az objektumfa gyökeréhez. Ez lehetővé teszi, hogy az eseményt ott kezelje, ahol szükséges.
Itt bemutatjuk, hogyan nyílik meg a Grid a SplitView, amikor a felhasználó megpróbálja a fókuszt a bal szélső fókuszálható vezérlő bal oldalára mozgatni (lásd: Tervezés Xboxhoz és TV-hez).
<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 és LostFocus események
A UIElement.GotFocus és a UIElement.LostFocus események akkor aktiválódnak, amikor egy elem fókuszba kerül, vagy elveszíti a fókuszt. Ez az esemény nem aktiválódik a TryMoveFocus esetében.
Mivel ezek továbbított események, a fókuszált elemtől indulva buborékszerűen haladnak felfelé az egymást követő szülőobjektumokon át az objektumfa gyökeréhez. Ez lehetővé teszi, hogy az eseményt ott kezelje, ahol szükséges.
GettingFocus és LosingFocus események
A UIElement.GettingFocus és az UIElement.LosingFocus események a megfelelő UIElement.GotFocus és UIElement.LostFocus események előtt aktiválódnak.
Mivel ezek továbbított események, a fókuszált elemtől indulva buborékszerűen haladnak felfelé az egymást követő szülőobjektumokon át az objektumfa gyökeréhez. Mivel ez a fókuszváltás előtt történik, átirányíthatja vagy megszakíthatja a fókuszmódosítást.
A FókuszMegkapás és a FókuszElvesztés szinkron események, így a fókusz nem lesz áthelyezve, amíg ezek az események buborékolnak. A GotFocus és a LostFocus azonban aszinkron események, ami azt jelenti, hogy nincs garancia arra, hogy a fókusz nem mozdul el újra a kezelő végrehajtása előtt.
Ha a fókusz a Control.Focus hívásán keresztül történik, a GettingFocus a hívás során van kiváltva, míg a GotFocus a hívás után lesz kiváltva.
A fókusznavigációs cél a GettingFocus és a LosingFocus események során (a fókusz áthelyezése előtt) módosítható a GettingFocusEventArgs.NewFocusedElement tulajdonságon keresztül. Még ha a cél is módosul, az esemény továbbra is buborékol, és a cél újból módosítható.
A reentranciai problémák elkerülése érdekében kivétel kerül dobásra, ha a fókuszt (TryMoveFocus vagy Control.Focus használatával) próbálja áthelyezni, amikor ezek az események felfutóban vannak.
Ezek az események a fókusz áthelyezésének okától függetlenül aktiválódnak (beleértve a tabulátoros navigációt, az irányított navigációt és a programozott navigációt).
A fókuszesemények végrehajtási sorrendje a következő:
- LosingFocus Ha a fókusz visszaáll a vesztes fókuszelemre, vagy a TryCancel sikeres, a rendszer nem aktivál további eseményeket.
- GettingFocus Ha a fókusz visszaáll a vesztes fókuszelemre, vagy a TryCancel sikeres, a rendszer nem aktivál további eseményeket.
- LostFocus
- GotFocus
Az alábbi képen látható, hogy az XYFocus hogyan választja ki a B4-et jelöltként, amikor az A-tól jobbra halad. A B4 ezután aktiválja a GettingFocus eseményt, ahol a ListView-nak lehetősége van a fókusz ismételt hozzárendelésére a B3-ra.
Fókusznavigációs cél módosítása a GettingFocus eseményen
Itt bemutatjuk, hogyan kezelheti a GettingFocus eseményt, és hogyan irányíthatja át a fókuszt.
<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;
}
}
}
Itt bemutatjuk, hogyan kezelheti egy parancssávLosingFocus eseményét, és hogyan állíthatja be a fókuszt a menü bezárásakor.
<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;
}
}
}
Az első és az utolsó fókuszba helyezhető elem megkeresése
A FocusManager.FindFirstFocusableElement és a FocusManager.FindLastFocusableElement metódusok áthelyezik a fókuszt az objektum hatókörén belül az első vagy utolsó fókuszba helyezhető elemre (egy UIElement elemfája vagy egy TextElement szövegfája). A hatókör a hívásban van megadva (ha az argumentum null, akkor a hatókör az aktuális ablak).
Ha a hatókörben nem azonosíthatók fókuszjelöltek, a rendszer null értéket ad vissza.
Itt bemutatjuk, hogyan adhatja meg, hogy a parancssáv gombjai körbefuttatásos irányban viselkedjenek (lásd : Billentyűzetműveletek).
<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;
}
}
}
Kapcsolódó cikkek
Windows developer