WPF – Odaklanma (Focus) Yönetimi


WPF – Odaklanma (Focus) Yönetimi

Bu makalemizde WPF (Windows Presentation Foundation) ile birlikte gelen odaklanma (focus) yeniliklerini öğrenmeye ve kullanmaya çalışacağız.

C# ya da VB.NET’ten alışık olduğumuz TabIndex’leri ayarlama \ sıralama ya da herhangi bir tetikleyiciye bağlı olarak Control.Focus() yazıp kullanma devri WPF’in getirdiği yeniliklerle beraber son buldu (Framework 3.0’dan beri). Klavye ve mantık odağı çerçevesinde çalışan bu odaklayıcıları tanımaya çalışmadan önce Windows Form’ları ve WPF Window’ları arasındaki Focus farklarını aşağıdaki tablodan görmeye çalışalımr:


Tablodaki farklar dışında getirilen kolaylıkları birkaç cümleyle destekleyebiliriz. Yukarıda da değindiğimiz tabIndex’leri sıralama işlemi artık başımızı ağrıtmıyor. Eğer siz nesnelerinizin tabIndex’lerinizi ayarlamaz ve birazdan bahsedeceğimiz odaklanma türlerinden birini seçerseniz, o sizin yerinize hem Tab tuşuyla, hem de yön tuşlarıyla bu işlemi gerçekleştirebiliyor. TabIndex’ler özel olarak belirlenirse, sizin belirlediğiniz sıralamayla yön bulma işlemi gerçekleşiyor. Artık odaklanma işlemlerine odaklanmaya başlayabiliriz:

WPF’te odaklanma işlemi gerçekleştiğinde IsKeyboardFocused özelliği true oluyor. Bu özellik Keyboard sınıfında bulunan FocusedElement‘te yer alıyor. KeyboardNavigation sınıfı System.Windows.Input.KeyboardNavigation isim uzayında yer alıyor. KeyboardNavigationMode isimli enum sabitinde işimize epey yarayacak altı farklı odaklanma şekli bulunuyor:



Visual Studio 2010’da WPFOdaklanma isimli yeni bir WPF tasarısı (proje) oluşturuyoruz:


Tasarımızı oluşturduktan sonra menü oluşturalım ve kodları inceleyerek devam edelim:


<Menu KeyboardNavigation.TabNavigation=”Once”> satırında KeyboardNavigation sınıfındaki TabNavigation özelliği Once olarak ayarlanmış. TabNavigation özelliği mantıksal bir sıralama işlemi yapılmasını sağlıyor. Once ise daha önce söylediğimiz gibi yalnızca bir kere odaklanıyor. TabNavigation‘ın C# tarafındaki kullanımıysa şöyledir:

public static void SetTabNavigation( DependencyObject element, KeyboardNavigationMode mode )

Bu programı derleyip çalıştırdığımızda odaklanma işlemi yalnızca bir kere gerçekleştirilecektir. Aynı menü üzerinde TabNavigation özelliğini Continue yapmamız o menü üzerinde sürekli olarak odaklanma yapmamızı sağlayacaktır. Elbette bu odaklanam işlemi Tab tuşuyla olabileceği gibi yön tuşlarıyla da gerçekleştirilebilmektedir. Siz de diğer odaklanma türlerini tek tek deneyerek farklarını daha iyi anlayabilirsiniz. Elbette bu farkları görebilmek için tek bir menü nesnesi yeterli olmayacaktır. Farklı taşıyıcılar (container \ panel) ve nesneler üzerinde, KeyboardNavigationMode’u değiştirerek farkları gözlemeyebilirsiniz.

Bu XAML kodlarının C#’daki karşılığıysa aşağıdaki gibidir:

Menu menu1 = new Menu();

MenuItem item1 = new MenuItem();

MenuItem item2 = new MenuItem();

MenuItem item3 = new MenuItem();

MenuItem item4 = new MenuItem();

menu1.Items.Add(item1);

menu1.Items.Add(item2);

menu1.Items.Add(item3);

menu1.Items.Add(item4);

KeyboardNavigation.SetTabNavigation(menu1, keyboardNavigationMode.Once);

Şimdi senaryomuzu değiştirelim ve kodlarımızı şu şekilde yazalım:


Programı derleyip çalıştırdığımızda düğmeler grubundan düğmeler 2 grubuna geçelim (bunu yapmak için sağ yön tuşunu kullanın.). düğmeler 2 grubuna geçildiğinde, düğmeler grubuna geçmek için sol yön tuşuna basın. O gruptan çıkılamadığını göreceksiniz. Bu kodların biraz önce yazmış olduğumuz kodlardan bir farkı var. Bundan önce yazdığımız kodlarda TabNavigation’ı kullanmışken şimdiyse DirectionalNavigation özelliğini kullandık. Bu özellik bizim yön tuşlarıyla (yalnızca sağ ve sol) hareket etme yeteneğimizi belirlemektedir. Kısacası yönlerle yol bulmamızı \ geçiş yapmamızı sağlar. Bu özelliğin varsayılan değeri Continue’dur. Obejct türünden olan bu özellik, C# tarafında da şu şekilde kullanılıyor:

public static void SetDirectionalNavigation( DependencyObject element, KeyboardNavigationMode mode )

Bunların dışında FocusManager sınıfındaki IsFocusScope özelliğine göz atmakta yarar var. Söz dizimine göz atarak başlayalım:

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

IsFocusScope alışık olduğumuz kalıbın dışında değil, yani isminden bool türünde olduğunu anlayabiliriz.🙂 Bu özellik sayesinde; bir bütün ait parçaların her birisi için farklı odaklanma ya da odaklanmama durumu belirleyebiliyoruz. Peki buna neden gereksinim duyuyoruz? Örneğin bir tab control’ümüz olduğunu ve her bir sekmede farklı veri girişleri \ gösterimleri yaptığımızı varsayalım. İkinci sekmede bir veri girişi yapıldığında ya da bir alanda düzeltme vb. bir işlem yapıldığında, bir başka sekmeye geçtiğimizi düşünün. Tekrar işlem yaptığımız sekmeye geçmek istediğimiz en son işlem yaptığımız alan yerine ilk alana odaklanacaktır. Bunun için odak hafızası ya da vb. bir mantık kullanma gereksinimi duyarız. Elbette bunun büyük bir sorun olmadığını da düşünebiliriz ama sinir bozucu olduğunu kabul etmek zorundayız.🙂 Tüm bu ve benzer senaryolar için IsFocusScope özelliğini kullanabiliriz. Bu bahsettiğim senaryoyla ilgili küçük bir örneği Daniel Grunwald‘ın makalesinde bulabilirsiniz.

Bir projede varsayılan olarak odaklnma türünü ayarlayabiliyoruz. Her nesne için kullanabileceğimiz (örneğin aşağıdaki GroupBox) yön bulma \ odaklanma ayarlarını yapılandırabiliyoruz:

<Window.Resources>
<Style TargetType=”GroupBox”>
<Setter Property=”Background” Value=”Transparent”/>
<Setter Property=”KeyboardNavigation.TabNavigation” Value=”Cycle”/>
<Setter Property=”KeyboardNavigation.ControlTabNavigation” Value=”Once”/>
</Style>
</Window.Resources>

Burada daha önce karşılaşmadığımız bir özellik daha bulunuyor, o da ControlTabNavigation. Bu özellik kontrollerde mantıksal sıralama işlemi yapılmasını sağlıyor. Yukarıda belirtilen tüm enum sabitleri (Once, Continue, None vd.) bu özellik için de kullanılabilmektedir. DirectionalNavigation özelliğinde olduğu gibi varsayılan değer Continue‘dur.

Tüm bunların yanısıra odaklanmaya (focus) ait olaylar (event) da bulunuyor: PreviewGotKeyboardFocus, GotKeyboardFocus ve PreviewLostKeyboardFocus, LostKeyboardFocus. Örnek bir XAML ve C# olayı aşağıdaki gibi olacaktır:

<TextBox Height=”23″

HorizontalAlignment=”Left”

Margin=”151,76,0,0″ Name=”textBox1″

VerticalAlignment=”Top”

GotKeyboardFocus=”TextBoxGotKeyboardFocus”

Width=”120″ />

private void TextBoxGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)

{

TextBox txt = e.Source as TextBox;

if (txt != null)

{

txt.Background = Brushes.Red;

}

}

Bu makalede öğrendiklerimizi kısaca tekrarlamak gerekirse:

  • Klasik Windows uygulamaları ve WPF uygulamalarındaki odaklanma (focus) farkları,
  • WPF’le beraber gelen altı farklı odak türleri (KeyboardNavigationMode enumu),
  • Bu odak türlerinin ne işe yaradığını ve nasıl kullanılabileceğini,
  • XAML ve C# kodlarını inceledik.

MSDN‘in sitesinde de yazdığı üzere; klavye – mantık odaklı çalışmasını ve diğer özelliklerin kullanımı daha iyi kavramak için farklı farklı senaryolar geliştirip işi biraz karmaşıklaştırmak gerektiğini düşünüyorum.

Kaynaklar

MSDN

C-SharpCorner

DotNetSpark

Umarım yararlı olabilmişimdir.

Hoşçakalın.

Mehmet KAPLAN
mehmet.kaplan@hotmail.com.tr

Hakkında Mehmet KAPLAN
mehmet.kaplan@hotmail.com.tr https://mehmetkaplan.wordpress.com/mehmetkaplan/

Bir Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Log Out / Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Log Out / Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Log Out / Değiştir )

Google+ fotoğrafı

Google+ hesabınızı kullanarak yorum yapıyorsunuz. Log Out / Değiştir )

Connecting to %s

%d blogcu bunu beğendi: