Odağa Genel Bakış

WPF'de odaklanmayla ilgili iki ana kavram vardır: klavye odağı ve mantıksal odak. Klavye odağı, klavye girişi alan öğeye, mantıksal odak ise odağı olan bir odak kapsamındaki öğeye başvurur. Bu kavramlar bu genel bakışta ayrıntılı olarak ele alınmaktadır. Bu kavramlardaki farkı anlamak, odağın elde edilebileceği birden çok bölgeye sahip karmaşık uygulamalar oluşturmak için önemlidir.

Odak yönetimine katılan ana sınıflar sınıfı, FocusManager sınıfı ve ve ContentElementgibi UIElement temel öğe sınıflarıdırKeyboard. Temel öğeler hakkında daha fazla bilgi için bkz. Temel Öğelere Genel Bakış.

sınıfı Keyboard öncelikle klavye odağıyla ilgilenir ve FocusManager öncelikli olarak mantıksal odakla ilgilenir, ancak bu mutlak bir ayrım değildir. Klavye odağı olan bir öğenin de mantıksal odağı olur, ancak mantıksal odağı olan bir öğenin klavye odağı olması gerekmez. Bu, klavye odağı olan Keyboard öğeyi ayarlamak için sınıfını kullandığınızda, mantıksal odağı da öğeye ayarladığınızda görünür.

Klavye Odağı

Klavye odağı, şu anda klavye girişi alan öğeyi ifade eder. Tüm masaüstünde klavye odağı olan tek bir öğe olabilir. WPF'de, klavye odağı olan öğe olarak trueayarlanmıştırIsKeyboardFocused. sınıfındaki Keyboard statik özelliğiFocusedElement, şu anda klavye odağı olan öğeyi alır.

Bir öğenin klavye odağını alabilmesi için, Focusable temel öğelerdeki IsVisible ve özellikleri olarak trueayarlanmalıdır. Temel sınıf gibi Panel bazı sınıflar Focusable varsayılan olarak olarak ayarlanmıştır false ; bu nedenle, böyle bir öğenin klavye odağını alabilmesini istiyorsanız olarak ayarlamanız Focusabletrue gerekir.

Klavye odağı, bir öğeye sekmeyle tıklama veya belirli öğelerdeki fareye tıklama gibi kullanıcı arabirimiyle etkileşim yoluyla elde edilebilir. Klavye odağı, sınıfındaki FocusKeyboard yöntemi kullanılarak program aracılığıyla da elde edilebilir. yöntemi, Focus belirtilen öğeye klavye odağı vermeyi dener. Döndürülen öğe, eski veya yeni odak nesnesi isteği engellerse istenenden farklı bir öğe olabilecek klavye odağına sahip öğedir.

Aşağıdaki örnek, klavye odağını bir Buttonüzerinde ayarlamak için yöntemini kullanırFocus.

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

IsKeyboardFocused Temel öğe sınıflarında özelliği, öğenin klavye odağı olup olmadığını belirten bir değer alır. IsKeyboardFocusWithin Temel öğe sınıflarında özelliği, öğenin veya görsel alt öğelerinden herhangi birinin klavye odağına sahip olup olmadığını belirten bir değer alır.

İlk odağı uygulama başlangıcında ayarlarken, odağı alacak öğe uygulama tarafından yüklenen ilk pencerenin görsel ağacında olmalı ve öğesinde Focusable ve IsVisible olarak ayarlanmalıdır true. İlk odağı ayarlamak için önerilen yer olay işleyicisindedir Loaded . Geri Dispatcher çağırma, veya BeginInvokeçağrılarak Invoke da kullanılabilir.

Mantıksal Odak

Mantıksal odak, odak kapsamındaki öğesine FocusManager.FocusedElement başvurur. Odak kapsamı, kapsamı içindeki öğesini FocusedElement izleyen bir öğedir. Klavye odağı odak kapsamından ayrıldığında, odaklanan öğe klavye odağını kaybeder ancak mantıksal odağı korur. Klavye odağı odak kapsamına döndüğünde, odaklanmış öğe klavye odağını alır. Bu, klavye odağının birden çok odak kapsamı arasında değiştirilmesine olanak tanır, ancak odak kapsamına döndüğünde odak kapsamındaki odaklanmış öğenin klavye odağını yeniden kazanmasını sağlar.

Uygulamada mantıksal odağı olan birden çok öğe olabilir, ancak belirli bir odak kapsamında mantıksal odağı olan yalnızca bir öğe olabilir.

Klavye odağı olan bir öğenin ait olduğu odak kapsamı için mantıksal odağı vardır.

Bir öğe, ekli özelliği IsFocusScope olarak ayarlanarak Genişletilebilir Uygulama Biçimlendirme Dili'nde (XAML) odak kapsamına FocusManagertruedönüştürülebilir. Kodda bir öğe çağrılarak SetIsFocusScopeodak kapsamına dönüştürülebilir.

Aşağıdaki örnek StackPanel , ekli özelliği ayarlayarak bir odak kapsamı oluşturur IsFocusScope .

<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 belirtilen öğenin odak kapsamını döndürür.

WPF'de varsayılan olarak odak kapsamları olan sınıflar , MenuItem, ToolBarve ContextMenu'tirWindow.

GetFocusedElement belirtilen odak kapsamı için odaklanmış öğeyi alır. SetFocusedElement belirtilen odak kapsamında odaklanmış öğeyi ayarlar. SetFocusedElement genellikle ilk odaklanmış öğeyi ayarlamak için kullanılır.

Aşağıdaki örnek odaklanmış öğeyi bir odak kapsamına ayarlar ve odak kapsamının odaklanmış öğesini alır.

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

Klavye ile Gezinme

Sınıfı KeyboardNavigation , gezinti tuşlarından birine basıldığında varsayılan klavye odağı gezintisini uygulamaktan sorumludur. Gezinti tuşları şunlardır: SEKME, SHIFT+SEKME, CTRL+SEKME, CTRL+SHIFT+SEKME, UPARROW, DOWNARROW, LEFTARROW ve RIGHTARROW tuşları.

Bir gezinti kapsayıcısının gezinti davranışı, ControlTabNavigation, ve DirectionalNavigationekli KeyboardNavigation özellikleri TabNavigationayarlanarak değiştirilebilir. Bu özellikler türündedir KeyboardNavigationMode ve olası değerler , , ContainedLocal, Cycle, Onceve NonedeğerleridirContinue. Varsayılan değer olan Continue, öğesinin bir gezinti kapsayıcısı olmadığı anlamına gelir.

Aşağıdaki örnek, bir dizi MenuItem nesne içeren bir Menu oluşturur. TabNavigation Ekli özellik üzerinde Menuolarak Cycle ayarlanır. içindeki sekme tuşu Menukullanılarak odak değiştirildiğinde, odak her öğeden taşınır ve son öğeye ulaşıldığında odak ilk öğeye döner.

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

Odakla çalışacak ek API'ler ve'dir MoveFocusPredictFocus.

MoveFocus odağı uygulamadaki bir sonraki öğeye değiştirir. yönü TraversalRequest belirtmek için A kullanılır. FocusNavigationDirection geçirildiMoveFocus, farklı yönlere odaklanılabilir, örneğinFirst, , LastUp ve Down.

Aşağıdaki örnek, odaklanmış öğeyi değiştirmek için kullanır MoveFocus .

// 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 , odak değiştirilecekse odağı alacak nesneyi döndürür. Şu anda yalnızca Up, Down, Leftve Right tarafından PredictFocusdesteklenir.

Odak Olayları

Klavye odağıyla ilgili olaylar , ve ve şeklindedirPreviewGotKeyboardFocusLostKeyboardFocus.PreviewLostKeyboardFocusGotKeyboardFocus Olaylar, sınıfta ekli olaylar olarak tanımlanır, ancak temel öğe sınıflarında Keyboard eşdeğer yönlendirilmiş olaylar olarak daha kolay erişilebilir. Olaylar hakkında daha fazla bilgi için bkz. Yönlendirilmiş Olaylara Genel Bakış.

GotKeyboardFocus öğesi klavye odağını elde ettiğinde oluşturulur. LostKeyboardFocus öğesi klavye odağını kaybettiğinde oluşturulur. PreviewGotKeyboardFocus Olay veya PreviewLostKeyboardFocusEvent olay işlenir ve Handled olarak trueayarlanırsa odak değişmez.

Aşağıdaki örnek, öğesine TextBoxekler GotKeyboardFocus ve LostKeyboardFocus olay işleyicileri ekler.

<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 Klavye odağı elde ettiğinde, Background özelliğini olarak TextBox değiştirilirLightBlue.

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 Klavye odağı kaybedildiğinde özelliğinin BackgroundTextBox özelliği beyaz olarak değiştirilir.

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

Mantıksal odakla ilgili olaylar ve LostFocusşeklindedirGotFocus. Bu olaylar üzerinde FocusManager ekli olaylar olarak tanımlanır, ancak FocusManager CLR olay sarmalayıcılarını kullanıma sunmaz. UIElement ve ContentElement bu olayları daha rahat kullanıma sunar.

Ayrıca bkz.