Odaklanmaya 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 Keyboard sınıfı, FocusManager sınıfı ve UIElement ve ContentElementgibi temel öğe sınıflarıdır. Temel öğeler hakkında daha fazla bilgi için bkz. Temel Öğelere Genel Bakış.
Keyboard sınıfı ö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ğına sahip olan öğeyi ayarlamak için Keyboard sınıfını kullandığınızda belirgin hale gelir; çünkü bu sınıf, aynı zamanda mantıksal odağı da öğeye ayarlar.
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 IsKeyboardFocusedtrue
olarak ayarlanır.
Keyboard sınıfının FocusedElement adlı statik özelliği, klavye odağına şu anda sahip olan öğeyi alır.
Bir öğenin klavye odağını alabilmesi için, temel öğelerdeki Focusable ve IsVisible özellikleri true
olarak ayarlanmalıdır.
Panel temel sınıfı gibi bazı sınıfların varsayılan olarak Focusablefalse
olarak ayarlanmıştır; bu nedenle, böyle bir öğenin klavye odağını elde edebilmesini istiyorsanız Focusabletrue
olarak ayarlamanız 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ğı, Keyboard sınıfındaki Focus yöntemi kullanılarak program aracılığıyla da elde edilebilir. Focus yöntemi, belirtilen öğe klavye odağını vermeyi dener. Döndürülen öğe, klavye odağına sahip olan öğedir ve eski veya yeni odak nesnesi isteği engellerse, istenenden farklı bir öğe olabilir.
Aşağıdaki örnek, klavye odağını Buttonayarlamak için Focus yöntemini kullanır.
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
Temel öğe sınıflarında IsKeyboardFocused özelliği, öğenin klavye odağı olup olmadığını belirten bir değer alır. Temel öğe sınıflarında IsKeyboardFocusWithin özelliği, öğenin veya görsel alt öğelerinden herhangi birinin klavye odağı olup olmadığını belirten bir değer alır.
İlk odağı uygulama başlangıcında ayarlarken, odağı alacak öğenin uygulama tarafından yüklenen ilk pencerenin görsel ağacında olması ve öğesinin Focusable ve IsVisibletrue
olarak ayarlanmış olması gerekir. İlk odağı ayarlamak için önerilen yer Loaded olay işleyicisindedir.
Dispatcher geri çağırma, Invoke veya BeginInvokeçağrılarak da kullanılabilir.
Mantıksal Odak
Mantık odağı, odak alanındaki FocusManager.FocusedElement'a atıfta bulunur. Odak kapsamı, kapsamı içinde 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ğına sahip bir öğenin ait olduğu odak kapsamı için mantıksal odağı vardır.
Bir öğe, IsFocusScope ekli FocusManager özelliği true
olarak ayarlanarak Genişletilebilir Uygulama Biçimlendirme Dili'nde (XAML) odak kapsamına dönüştürülebilir. Kodda, bir öğe SetIsFocusScopeçağrılarak odak kapsamına dönüştürülebilir.
Aşağıdaki örnek, IsFocusScope ekli özelliği ayarlayarak StackPanel'ı bir odak kapsamı haline getirir.
<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 Window, MenuItem, ToolBarve ContextMenu.
GetFocusedElement belirtilen odak kapsamı için odaklanmış öğeyi elde eder. 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 Gezintisi
KeyboardNavigation sınıfı, 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, YUKARI OK, AŞAĞI OK, SOL OK ve SAĞ OK tuşları.
Gezinti kapsayıcısının gezinti davranışı, TabNavigation, ControlTabNavigationve DirectionalNavigationekli KeyboardNavigation özellikleri ayarlanarak değiştirilebilir. Bu özellikler KeyboardNavigationMode türündedir ve olası değerler Continue, Local, Contained, Cycle, Onceve None. Varsayılan değer Continuedeğeridir; bu da öğenin bir gezinti kapsayıcısı olmadığı anlamına gelir.
Aşağıdaki örnek, bir dizi MenuItem nesnesi içeren bir Menu oluşturur. TabNavigation ekli özelliği, Menuüzerinde Cycle olarak ayarlanmıştır. odak, Menuiçindeki sekme tuşu kullanılarak 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)
Odak Noktasını Program Aracılığıyla Yönlendirme
Odakla çalışmak için ek bir API MoveFocus ve PredictFocus'dir.
MoveFocus, odağı uygulamadaki bir sonraki öğeye değiştirir. Yönü belirtmek için bir TraversalRequest kullanılır. FocusNavigationDirection öğesi MoveFocus'e geçtiğinde, odaklanmanın First, Last, Up ve Downgibi farklı yönlere hareket edebileceğini belirtir.
Aşağıdaki örnekte odaklanmış öğeyi değiştirmek için MoveFocus kullanılmaktadır.
// 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 RightPredictFocustarafından desteklenir.
Odak Olayları
Klavye odağıyla ilgili olaylar PreviewGotKeyboardFocus, GotKeyboardFocus ve PreviewLostKeyboardFocus, LostKeyboardFocus. Olaylar Keyboard sınıfında ekli olaylar olarak tanımlanır, ancak temel öğe sınıflarında 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, öğe klavye odağını aldığında oluşturulur. Öğe klavye odağını kaybettiğinde LostKeyboardFocus tetiklenir.
PreviewGotKeyboardFocus olayı veya PreviewLostKeyboardFocusEvent olayı işlenirse ve Handledtrue
olarak ayarlanırsa odak değişmez.
Aşağıdaki örnek, GotKeyboardFocus ve LostKeyboardFocus olay işleyicilerini bir TextBox'ye 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, TextBox'nin Background özelliği LightBlueolarak değiştirilir.
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ğını kaybettiğinde, TextBox'nin Background özelliği tekrar beyaza 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 GotFocus ve LostFocus. Bu olaylar, FocusManager üzerinde ekli olaylar olarak tanımlanır, ancak FocusManager CLR olay sarmalayıcılarını ortaya çıkarmaz. UIElement ve ContentElement bu olayları daha uygun bir şekilde açığa çıkarır.
Ayrıca bkz.
.NET Desktop feedback