Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Aby programowo przenieść fokus w aplikacji systemu Windows, możesz użyć metody FocusManager.TryMoveFocus lub metody FindNextElement .
TryMoveFocus próbuje zmienić fokus z elementu z fokusem na następny element z możliwością uzyskania fokusu w określonym kierunku, podczas gdy FindNextElement pobiera element (jako Obiekt DependencyObject), który będzie otrzymywać fokus jako pierwszy na podstawie określonego kierunku nawigacji (tylko nawigacja kierunkowa, nie można użyć do emulowania nawigacji na karcie).
Uwaga / Notatka
Zalecamy użycie metody FindNextElement zamiast FindNextFocusableElement, ponieważ FindNextFocusableElement pobiera UIElement, który zwraca wartość null, jeśli następny element fokusowy nie jest UIElement (takim jak Hiperłącze).
Znajdowanie kandydata fokusu w zakresie
Możesz dostosować zachowanie nawigacji dla TryMoveFocus i FindNextElement, włączając w to wyszukiwanie następnego kandydata do ustawienia ostrości w określonym drzewie interfejsu użytkownika lub wykluczenie z rozważania określonych elementów.
W tym przykładzie użyto gry TicTacToe w celu zademonstrowania metod TryMoveFocus i 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);
}
}
Użyj FindNextElementOptions, aby jeszcze bardziej dostosować sposób identyfikowania kandydatów fokusu. Ten obiekt zapewnia następujące właściwości:
- SearchRoot — ogranicz wyszukiwanie kandydatów do nawigacji fokusu do elementów podrzędnych tego obiektu DependencyObject. Wartość null wskazuje, aby rozpocząć wyszukiwanie od korzenia drzewa wizualnego.
Ważne
Jeśli do potomków SearchRoot stosowane są jedno lub więcej przekształceń, które umieszczają je poza obszarem kierunkowym, te elementy nadal są uznawane za kandydatów.
- ExclusionRect — kandydaci do nawigacji z fokusem są identyfikowani przy użyciu "fikcyjnego" prostokąta granicznego, w którym wszystkie nakładające się obiekty są wykluczone z nawigacji z fokusem. Ten prostokąt jest używany tylko do obliczeń i nigdy nie jest dodawany do drzewa wizualizacji.
- HintRect — kandydaci nawigacji fokusu są identyfikowane przy użyciu fikcyjnego prostokąta ograniczenia, który identyfikuje elementy, które najprawdopodobniej otrzymają fokus. Ten prostokąt jest używany tylko do obliczeń i nigdy nie jest dodawany do drzewa wizualizacji.
- XYFocusNavigationStrategyOverride — strategia nawigacji fokusu służąca do określania najlepszego elementu kandydującego do przejęcia fokusu.
Na poniższej ilustracji przedstawiono niektóre z tych pojęć.
Gdy element B ma fokus, FindNextElement identyfikuje [I] jako kandydata fokusu podczas nawigacji w prawo. Oto następujące przyczyny:
- Ze względu na HintRect na A, odwołanie początkowe to A, a nie B
- C nie jest kandydatem, ponieważ MyPanel został określony jako SearchRoot
- F nie jest kandydatem, ponieważ element ExclusionRect nakłada się na niego
Dostosowane zachowanie nawigacji fokusu przy użyciu wskazówek nawigacji
Zdarzenia fokusu nawigacji
Zdarzenie NoFocusCandidateFound
Zdarzenie UIElement.NoFocusCandidateFound jest wywoływane za pomocą naciśnięcia tabulatora lub strzałek, gdy nie ma kandydata do fokusu w określonym kierunku. To zdarzenie nie jest wyzwalane dla funkcji TryMoveFocus.
Ponieważ jest to zdarzenie kierowane (routed event), propaguje się z elementu, który ma fokus, przez kolejne obiekty nadrzędne do korzenia drzewa obiektów. Umożliwia to obsługę zdarzenia wszędzie tam, gdzie jest to konieczne.
W tym miejscu pokażemy, jak siatka otwiera widok SplitView , gdy użytkownik próbuje przenieść fokus na lewo od lewej strony najbardziej skoncentrowanej kontrolki (zobacz Projektowanie dla konsoli Xbox i telewizora).
<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;
}
}
Zdarzenia GotFocus i LostFocus
Zdarzenia UIElement.GotFocus i UIElement.LostFocus są wyzwalane, gdy element uzyskuje fokus lub traci fokus odpowiednio. To zdarzenie nie jest wyzwalane dla funkcji TryMoveFocus.
Ponieważ są to zdarzenia kierowane, przenikają one z elementu, który ma fokus, przez kolejne obiekty nadrzędne do korzenia drzewa obiektów. Umożliwia to obsługę zdarzenia wszędzie tam, gdzie jest to konieczne.
Zdarzenia GettingFocus i LosingFocus
Zdarzenia UIElement.GettingFocus i UIElement.LosingFocus są uruchamiane przed odpowiednimi zdarzeniami UIElement.GotFocus i UIElement.LostFocus.
Ponieważ są to zdarzenia kierowane, propagują się z elementu skupionego przez kolejne obiekty nadrzędne do korzenia drzewa obiektów. Ponieważ dzieje się to przed zmianą fokusu, możesz przekierować lub anulować zmianę fokusu.
GettingFocus i LosingFocus są zdarzeniami synchronicznymi, więc fokus nie zostanie przeniesiony, gdy te zdarzenia zachodzą w fazie bąbelkowej. Jednak GotFocus i LostFocus są zdarzeniami asynchronicznymi, co oznacza, że nie ma gwarancji, że fokus nie zostanie przeniesiony ponownie przed wykonaniem programu obsługi.
Jeśli fokus przechodzi przez wywołanie Control.Focus, funkcja GettingFocus jest wywoływana podczas wywołania, podczas gdy funkcja GotFocus jest wywoływana po wywołaniu.
Cel nawigacji fokusu można zmienić podczas zdarzeń GettingFocus i LosingFocus (przed przeniesieniem fokusu) za pomocą właściwości GettingFocusEventArgs.NewFocusedElement . Nawet jeśli obiekt docelowy zostanie zmieniony, zdarzenie nadal bąbelkuje i obiekt docelowy można zmienić ponownie.
Aby uniknąć problemów z ponownym wejściem, wyjątek jest zgłaszany, gdy próbujesz przenieść fokus (używając TryMoveFocus lub Control.Focus) w trakcie propagowania się tych zdarzeń.
Te zdarzenia są wyzwalane niezależnie od przyczyny przenoszenia fokusu (w tym nawigacji przy użyciu klawisza Tab, nawigacji kierunkowej i nawigacji programistycznej).
Oto kolejność wykonywania zdarzeń fokusu:
- Utrata fokusu Jeśli fokus zostanie zresetowany z powrotem do elementu tracącego fokus lub TryCancel zakończy się pomyślnie, żadne dalsze zdarzenia nie zostaną wyzwolone.
- Fokusowanie Jeśli ostrość zostanie przywrócona do utraconego elementu fokusu lub TryCancel zakończy się pomyślnie, żadne dalsze zdarzenia nie zostaną wygenerowane.
- Utrata fokusa
- GotFocus
Na poniższej ilustracji pokazano, jak podczas przechodzenia do prawej strony od A XYFocus wybiera B4 jako kandydata. Następnie B4 uruchamia zdarzenie GettingFocus, w którym widok ListView ma możliwość ponownego przypisania fokusu do B3.
Zmienianie docelowego elementu nawigacji uwagi przy zdarzeniu GettingFocus
W tym miejscu pokazano, jak obsługiwać zdarzenie GettingFocus i przekierować 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;
}
}
}
W tym miejscu pokazano, jak obsługiwać zdarzenie LosingFocus dla paska poleceń i ustawiać fokus po zamknięciu menu.
<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;
}
}
}
Znajdź pierwszy i ostatni element z możliwością koncentracji uwagi
Metody FocusManager.FindFirstFocusableElement i FocusManager.FindLastFocusableElement przenoszą fokus do pierwszego lub ostatniego elementu fokusu w zakresie obiektu (drzewa elementów elementu UIElement lub drzewa tekstowego elementu TextElement). Zakres jest określony w wywołaniu (jeśli argument ma wartość null, zakres jest bieżącym oknem).
Jeśli w zakresie nie można zidentyfikować żadnych kandydatów fokusu, zwracana jest wartość null.
Pokazujemy tutaj, jak określić, że przyciski CommandBar mają kierunkowe zawijanie (zobacz Interakcje z klawiaturą).
<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;
}
}
}
Powiązane artykuły
Windows developer