Přehled fokusu

Ve WPF existují dva hlavní koncepty, které se týkají fokusu: fokus klávesnice a logický fokus. Fokus klávesnice odkazuje na prvek, který přijímá vstup klávesnice a logický fokus odkazuje na prvek v oboru fokusu, který má fokus. Tyto koncepty jsou podrobně popsány v tomto přehledu. Pochopení rozdílu v těchto konceptech je důležité pro vytváření složitých aplikací, které mají více oblastí, kde je možné získat zaměření.

Hlavní třídy, které se účastní správy fokusu Keyboard , jsou třída, FocusManager třída a základní třídy elementů, například UIElement a ContentElement. Další informace o základních elementech naleznete v přehledu základních elementů.

Třída Keyboard se zabývá především fokusem klávesnice a FocusManager zabývá se primárně logickým fokusem, ale nejedná se o absolutní rozdíl. Prvek s fokusem klávesnice bude mít také logický fokus, ale prvek, který má logický fokus, nemusí mít fokus klávesnice. To je zřejmé, když použijete Keyboard třídu k nastavení elementu, který má fokus klávesnice, pro něj také nastaví logický fokus na prvek.

Fokus klávesnice

Fokus klávesnice odkazuje na prvek, který aktuálně přijímá vstup klávesnice. Na celé ploše může být jenom jeden prvek, který má fokus klávesnice. Ve WPF bude IsKeyboardFocused prvek s fokusem klávesnice nastaven na true. Statická vlastnost FocusedElement třídy Keyboard získá prvek, který má aktuálně fokus klávesnice.

Aby prvek získal fokus klávesnice, FocusableIsVisible musí být vlastnosti základních prvků nastaveny na truehodnotu . Některé třídy, jako Panel je základní třída, jsou ve výchozím nastavení nastaveny Focusablefalse . Proto je nutné nastavit Focusabletrue , aby takový prvek mohl získat fokus klávesnice.

Fokus klávesnice lze získat prostřednictvím interakce uživatele s uživatelským rozhraním, například tabulátorem na prvek nebo kliknutím myši na určité prvky. Fokus klávesnice lze získat také programově pomocí Focus metody ve Keyboard třídě. Metoda Focus se pokusí poskytnout zadaný prvek klávesnice fokus. Vrácený prvek je prvek, který má fokus klávesnice, což může být jiný prvek než požadovaný, pokud starý nebo nový objekt fokusu zablokuje požadavek.

Následující příklad používá metodu Focus k nastavení fokusu Buttonklávesnice na .

private void OnLoaded(object sender, RoutedEventArgs e)
{
    // Sets keyboard focus on the first Button in the sample.
    Keyboard.Focus(firstButton);
}
Private Sub OnLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
    ' Sets keyboard focus on the first Button in the sample.
    Keyboard.Focus(firstButton)
End Sub

Vlastnost IsKeyboardFocused základní třídy elementu získá hodnotu určující, zda prvek má fokus klávesnice. Vlastnost IsKeyboardFocusWithin základní třídy elementu získá hodnotu určující, zda prvek nebo některý z jeho vizuální podřízených elementů má fokus klávesnice.

Při nastavování počátečního fokusu při spuštění aplikace musí být prvek pro příjem fokusu ve vizuálním stromu počátečního okna načteného aplikací a prvek musí mít Focusable a IsVisible nastaven na true. Doporučeným místem pro nastavení počátečního fokusu je obslužná rutina Loaded události. Dispatcher Zpětné volání lze použít také voláním Invoke nebo BeginInvoke.

Logický fokus

Logický fokus odkazuje na FocusManager.FocusedElement rozsah fokusu. Rozsah fokusu je prvek, který sleduje rozsah FocusedElement v rámci oboru. Když fokus klávesnice opustí obor fokusu, prioritní prvek ztratí fokus klávesnice, ale zachová logický fokus. Když se fokus klávesnice vrátí do oboru fokusu, získá fokus klávesnice. To umožňuje změnit fokus klávesnice mezi více fokusovými obory, ale zajistí, aby fokus fokus fokusu znovu získal, když se fokus vrátí do oboru fokusu.

V aplikaci může existovat více prvků, které mají logický fokus, ale může existovat pouze jeden prvek, který má logický fokus v konkrétním oboru fokusu.

Prvek s fokusem klávesnice má logický fokus pro rozsah fokusu, do kterého patří.

Prvek lze převést na rozsah fokusu v jazyku XAML (Extensible Application Markup Language) nastavením FocusManager připojené vlastnosti IsFocusScope na true. V kódu lze prvek převést na rozsah fokus voláním SetIsFocusScope.

Následující příklad vytvoří StackPanel obor fokusu nastavením IsFocusScope připojené vlastnosti.

<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);
Dim focuseScope2 As New StackPanel()
FocusManager.SetIsFocusScope(focuseScope2, True)

GetFocusScope vrátí rozsah fokusu pro zadaný prvek.

Třídy ve WPF, které jsou ve výchozím nastavení rozsahy fokusu, jsou Window, MenuItem, ToolBara ContextMenu.

GetFocusedElement získá prioritní prvek pro zadaný rozsah fokusu. SetFocusedElement nastaví prioritní prvek v zadaném rozsahu fokusu. SetFocusedElement se obvykle používá k nastavení počátečního prioritního prvku.

Následující příklad nastaví prioritní prvek na rozsah fokusu a získá prioritní prvek oboru fokusu.

// 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);
' Sets the focused element in focusScope1
' focusScope1 is a StackPanel.
FocusManager.SetFocusedElement(focusScope1, button2)

' Gets the focused element for focusScope 1
Dim focusedElement As IInputElement = FocusManager.GetFocusedElement(focusScope1)

Navigace s použitím klávesnice

Třída KeyboardNavigation zodpovídá za implementaci výchozí navigace fokusu klávesnice při stisknutí některé z navigačních kláves. Navigační klávesy jsou: TAB, SHIFT+TAB, CTRL+TAB, CTRL+SHIFT+TAB, UPARROW, DOWNARROW, LEFTARROW a RIGHTARROW.

Chování navigace v navigačním kontejneru lze změnit nastavením připojených KeyboardNavigation vlastností TabNavigation, ControlTabNavigationa DirectionalNavigation. Tyto vlastnosti jsou typu KeyboardNavigationMode a možné hodnoty jsou Continue, Local, Contained, Cycle, , Oncea None. Výchozí hodnota je Continue, což znamená, že prvek není navigační kontejner.

Následující příklad vytvoří s Menu několika MenuItem objekty. Připojená TabNavigation vlastnost je nastavena na Cycle .Menu Když se fokus změní pomocí klávesy Tab v rámci objektu Menu, fokus se přesune z každého prvku a po dosažení posledního prvku se vrátí k prvnímu prvku.

<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);
Dim navigationMenu As New Menu()
Dim item1 As New MenuItem()
Dim item2 As New MenuItem()
Dim item3 As New MenuItem()
Dim item4 As New MenuItem()

navigationMenu.Items.Add(item1)
navigationMenu.Items.Add(item2)
navigationMenu.Items.Add(item3)
navigationMenu.Items.Add(item4)

KeyboardNavigation.SetTabNavigation(navigationMenu, KeyboardNavigationMode.Cycle)

Další rozhraní API pro práci s fokusem jsou MoveFocus a PredictFocus.

MoveFocus změní fokus na další prvek aplikace. A TraversalRequest slouží k určení směru. Předání FocusNavigationDirection určuje různé směry fokusu, například First, , LastUp a Down.MoveFocus

Následující příklad používá MoveFocus ke změně prioritního prvku.

// 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);
}
' Creating a FocusNavigationDirection object and setting it to a
' local field that contains the direction selected.
Dim focusDirection As FocusNavigationDirection = _focusMoveValue

' MoveFocus takes a TraveralReqest as its argument.
Dim request As New TraversalRequest(focusDirection)

' Gets the element with keyboard focus.
Dim elementWithFocus As UIElement = TryCast(Keyboard.FocusedElement, UIElement)

' Change keyboard focus.
If elementWithFocus IsNot Nothing Then
    elementWithFocus.MoveFocus(request)
End If

PredictFocus vrátí objekt, který by obdržel fokus, pokud by se fokus změnil. V současné době jsou podporovány pouze Up, DownLeft, a Right jsou podporovány PredictFocus.

Události fokusu

Události související s fokusem klávesnice jsou PreviewGotKeyboardFocusa GotKeyboardFocusPreviewLostKeyboardFocus, LostKeyboardFocus. Události jsou definovány jako připojené události třídy Keyboard , ale jsou snadněji přístupné jako ekvivalentní směrované události na základních třídách elementů. Další informace o událostech najdete v přehledu směrovaných událostí.

GotKeyboardFocus je vyvolána, když prvek získá fokus klávesnice. LostKeyboardFocus je vyvolána, když prvek ztratí fokus klávesnice. Pokud je PreviewGotKeyboardFocus událost nebo PreviewLostKeyboardFocusEvent událost zpracována a Handled je nastavena na true, fokus se nezmění.

Následující příklad připojí GotKeyboardFocus a LostKeyboardFocus obslužné rutiny událostí k .TextBox

<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>

TextBox Když získá fokus klávesnice, Background vlastnost objektu TextBox se změní na LightBlue.

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();
    }
}
Private Sub TextBoxGotKeyboardFocus(ByVal sender As Object, ByVal e As KeyboardFocusChangedEventArgs)
    Dim source As TextBox = TryCast(e.Source, TextBox)

    If source IsNot Nothing Then
        ' Change the TextBox color when it obtains focus.
        source.Background = Brushes.LightBlue

        ' Clear the TextBox.
        source.Clear()
    End If
End Sub

TextBox Když ztratí fokus klávesnice, Background vlastnost objektu TextBox se změní zpět na bílou.

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();
    }
}
Private Sub TextBoxLostKeyboardFocus(ByVal sender As Object, ByVal e As KeyboardFocusChangedEventArgs)
    Dim source As TextBox = TryCast(e.Source, TextBox)

    If source IsNot Nothing Then
        ' Change the TextBox color when it loses focus.
        source.Background = Brushes.White

        ' Set the  hit counter back to zero and updates the display.
        Me.ResetCounter()
    End If
End Sub

Události související s logickým fokusem jsou GotFocus a LostFocus. Tyto události jsou definovány jako FocusManager připojené události, ale FocusManager nezpřístupňuje obálky událostí CLR. UIElement a ContentElement zpřístupnit tyto události pohodlněji.

Viz také