Dela via


Fokusöversikt

I WPF finns det två huvudsakliga begrepp som gäller fokus: tangentbordsfokus och logiskt fokus. Tangentbordsfokus refererar till elementet som tar emot tangentbordsindata och logiskt fokus refererar till elementet i ett fokusomfång som har fokus. Dessa begrepp beskrivs i detalj i den här översikten. Att förstå skillnaden i dessa begrepp är viktigt för att skapa komplexa program som har flera regioner där fokus kan hämtas.

De viktigaste klasserna som deltar i fokushantering är klassen Keyboard, klassen FocusManager och baselementklasserna, till exempel UIElement och ContentElement. Mer information om baselementen finns i Base Elements Overview.

Klassen Keyboard handlar främst om tangentbordsfokus och FocusManager främst handlar om logiskt fokus, men detta är inte en absolut skillnad. Ett element som har tangentbordsfokus kommer också att ha logiskt fokus, men ett element som har logiskt fokus har inte nödvändigtvis tangentbordsfokus. Detta är uppenbart när du använder klassen Keyboard för att ange elementet som har tangentbordsfokus, för det ställer även in logiskt fokus på elementet.

Tangentbordsfokus

Tangentbordsfokus refererar till det element som för närvarande tar emot tangentbordsindata. Det kan bara finnas ett element på hela skrivbordet som har tangentbordsfokus. I WPF har elementet som har tangentbordsfokus IsKeyboardFocused inställt på true. Den statiska egenskapen FocusedElement på klassen Keyboard hämtar elementet som för närvarande har tangentbordsfokus.

För att ett element ska få tangentbordsfokus måste egenskaperna Focusable och IsVisible på baselementen anges till true. Vissa klasser, till exempel basklassen Panel, har Focusable inställt på false som standard. Därför måste du ange Focusable till true om du vill att ett sådant element ska kunna få tangentbordsfokus.

Tangentbordsfokus kan hämtas via användarinteraktion med användargränssnittet, till exempel tabbning till ett element eller klicka med musen på vissa element. Tangentbordsfokus kan också hämtas programmatiskt med hjälp av metoden Focus i klassen Keyboard. Metoden Focus försöker ge det angivna elementets tangentbord fokus. Det returnerade elementet är det element som har tangentbordsfokus, vilket kan vara ett annat element än vad som begärdes om antingen det gamla eller nya fokusobjektet blockerar begäran.

I följande exempel används metoden Focus för att ange tangentbordsfokus på en Button.

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

Egenskapen IsKeyboardFocused för baselementklasserna får ett värde som anger om elementet har tangentbordsfokus. Egenskapen IsKeyboardFocusWithin på baselementklasserna får ett värde som anger om elementet eller något av dess underordnade visuella element har tangentbordsfokus.

När du ställer in inledande fokus vid programstart måste elementet som ska få fokus vara i det visuella trädet i det första fönstret som läses in av programmet, och elementet måste ha Focusable och IsVisible inställt på true. Den rekommenderade platsen för att ange inledande fokus finns i Loaded händelsehanteraren. Ett Dispatcher återanrop kan också användas genom att anropa Invoke eller BeginInvoke.

Logiskt fokus

Logiskt fokus hänvisar till FocusManager.FocusedElement i ett fokusområde. Ett fokusområde är ett element som spårar FocusedElement inom sitt område. När tangentbordsfokus lämnar ett fokusomfång förlorar det fokuserade elementet tangentbordsfokus men behåller logiskt fokus. När tangentbordsfokus återgår till fokusomfånget får det fokuserade elementet tangentbordsfokus. Detta gör att tangentbordsfokus kan ändras mellan flera fokusomfattningar, men säkerställer att det fokuserade elementet i fokusomfånget återfår tangentbordsfokus när fokus återgår till fokusomfånget.

Det kan finnas flera element som har logiskt fokus i ett program, men det kan bara finnas ett element som har logiskt fokus i ett visst fokusomfång.

Ett element som har tangentbordsfokus har logiskt fokus för det fokusomfång som det tillhör.

Ett element kan omvandlas till ett fokusomfång i XAML (Extensible Application Markup Language) genom att ange den FocusManager kopplade egenskapen IsFocusScope till true. I kod kan ett element omvandlas till ett fokusomfång genom att anropa SetIsFocusScope.

Följande exempel gör en StackPanel till ett fokusomfång genom att ange den IsFocusScope kopplade egenskapen.

<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 returnerar fokusomfånget för det angivna elementet.

Klasser i WPF som är fokusomfattningar som standard är Window, MenuItem, ToolBaroch ContextMenu.

GetFocusedElement hämtar det fokuserade elementet för det angivna fokusomfånget. SetFocusedElement anger det fokuserade elementet i det angivna fokusomfånget. SetFocusedElement används vanligtvis för att ange det första fokuserade elementet.

I följande exempel ställs det fokuserade elementet in på ett fokusomfång och det fokuserade elementet i ett fokusomfång hämtas.

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

Tangentbordsnavigering

Klassen KeyboardNavigation ansvarar för att implementera standardtangentbordets fokusnavigering när en av navigeringstangenterna trycks in. Navigeringsnycklarna är: TAB, SKIFT+TAB, CTRL+TAB, CTRL+SKIFT+TAB, UPARROW, DOWNARROW, LEFTARROW och RIGHTARROW.

Navigeringsbeteendet för en navigeringscontainer kan ändras genom att ange de anslutna KeyboardNavigation egenskaperna TabNavigation, ControlTabNavigationoch DirectionalNavigation. De här egenskaperna är av typen KeyboardNavigationMode och de möjliga värdena är Continue, Local, Contained, Cycle, Onceoch None. Standardvärdet är Continue, vilket innebär att elementet inte är en navigeringscontainer.

I följande exempel skapas en Menu med ett antal MenuItem objekt. Den associerade egenskapen TabNavigation är inställd på Cycle för Menu. När fokus ändras med hjälp av tabbtangenten i Menuflyttas fokus från varje element och när det sista elementet har nåtts återgår fokus till det första elementet.

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

Ytterligare API för att arbeta med fokus är MoveFocus och PredictFocus.

MoveFocus ändrar fokus till nästa element i programmet. En TraversalRequest används för att ange riktningen. Den FocusNavigationDirection som skickas till MoveFocus anger de olika riktningar som fokus kan flyttas, till exempel First, Last, Up och Down.

I följande exempel används MoveFocus för att ändra det fokuserade elementet.

// 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 returnerar objektet som skulle få fokus om fokus skulle ändras. För närvarande stöds endast Up, Down, Leftoch Right av PredictFocus.

Fokushändelser

Händelserna som rör tangentbordsfokus är PreviewGotKeyboardFocus, GotKeyboardFocus och PreviewLostKeyboardFocus, LostKeyboardFocus. Händelserna definieras som kopplade händelser i klassen Keyboard, men är mer lättillgängliga som motsvarande dirigerade händelser i baselementklasserna. För mer information om händelser, se översikten över routade händelser.

GotKeyboardFocus höjs när elementet får tangentbordsfokus. LostKeyboardFocus aktiveras när elementet förlorar tangentbordsfokus. Om händelsen PreviewGotKeyboardFocus eller PreviewLostKeyboardFocusEvent hanteras och Handled är inställd på trueändras inte fokus.

I följande exempel kopplas GotKeyboardFocus- och LostKeyboardFocus händelsehanterare till en 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>

När TextBox får tangentbordsfokus ändras egenskapen Background för TextBox till 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

När TextBox förlorar tangentbordsfokus ändras egenskapen Background för TextBox tillbaka till vit.

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

Händelserna som rör logiskt fokus är GotFocus och LostFocus. Dessa händelser definieras på FocusManager som bifogade händelser, men FocusManager exponerar inte CLR-händelseomslag. UIElement och ContentElement göra dessa händelser mer tillgängliga.

Se även