Herkese merhabalar,

Uzun bir aradan sonra kaldığım yerden devam ediyorum. Biliyorum arayı biraz soğuttum çünkü bu süre zarfında öğrencilik hayatından iş hayatına bir geçiş durumum ve bazı extreme durumlar söz konusuydu. Neyse güzel olan tekrar yazı yazıyor olmam değil miJGelelim bugünkü yazıma. WPF’te behavior dediğimiz yapılardan bahsedeceğim.

Peki nedir bu behavior?

WPF’te bildiğiniz gibi elementlerin görselliğini değiştirmek için stiller uygulanır. Stillerimizi bir Resource da tutarak gerektiği yerde ulaşarak kullanabilmekteyiz, aynı  html’deki css (cascading style sheet) mantığı gibi. Stiller bize düzenli, iyi organize edilmiş ve tutarlı bir kullanıcı arayüzü oluşturmada oldukça iyi bir altyapı sağlamaktadır fakat yeterli değildir. Stiller, tipik bir WPF uygulamasında kullanıcı arayüzü altyapısının sadece küçük bir parçasını oluşturmaktadır. Bazı uygulamalar kod tarafında da sürükle bırak, zoom ve yerleştirme gibi kullanıcı arayüzü işlevleri tanımlanmasını gerektirmektedir ve her bir yeni WPF projemizde bu kodları tekrar tekrar yazmak durumunda kalacağız. İşte burada behavior dediğimiz yapı devreye girmektedir. Behavior’lar sayesinde UI etkileşimli kodlarınızı tekrar tekrar kullanabilirsiniz.

Nasıl oluşturulur ve kullanılır?

Expression Blend’i açtığınızda Behaviors isimli panelde Blend’in size sunmuş olduğu hali hazırdaki behaviorları bulabilirsiniz veya kendi behavior’ınızı oluşturup buraya ekleyebilirsiniz. Behavior’ların amacı UI fonksiyonellikleri oluşturmaktır. Bu sayede kod yazmadan elementlere uygulayabiliriz. Her bir behavior’ın tek bir işlevi vardır. Behavior’ları anlamanın en iyi yolu kendi behavior’ımızı yazmaktır. Bir Canvas’ın içindeki elementlere mouse ile sürükle bırakılabilirlik özelliği vermek istediğimizi düşünelim. Bunu birkaç satır kodla da yapabiliriz dediğinizi duyar gibiyim ama biraz fazla eforla tekrar tekrar kullanılabilir bir behavior oluşturabiliriz.

İşe öncelikle bir WPF Class Library projesi oluşturmakla başlayalım. Referans olarak da System.Windows.Interactivity dll dosyasını ekleyelim. Projemize bir sınıf ekleyerek aşağıdaki gibi Behavior temel sınıfından kalıtalım. Behavior sınıfı jenerik bir sınıftır ve bir tane tip argumanı alır. UIElement tipini kullanabiliriz eğer tüm elementler için uygulanabilir yapmak istiyorsanız FrameworkElement kullanabilirsiniz:

public class DragBehaviour:Behavior<UIElement>

 {...}

Behavior yazarken yapılması gereken ilk adım OnAttached() ve OnDetaching() metodlarını ezmektir. OnAttached metodu çağrıldığında behavior’ımızın yerleştirildiği elemente ulaşabiliriz(AssociatedObject property’si sayesinde) ve eventhandler tanımlayabiliriz. OnDetaching metodu çağrıldığında ise eventhandler’ları silebiliriz.Sürükle bırak olaylarını yakalayabilmek için behaviorın ilişkili olduğu elementin MouseLeftButtonDown,MouseMove ve MouseLeftButtonUp olaylarını aşağıdaki gibi tanımlamalıyız:

protected override void OnAttached(){

 base.OnAttached();
 AssociatedObject.MouseLeftButtonDown += AssociatedObject_MouseLeftButtonDown;
 AssociatedObject.MouseMove +=AssociatedObject_MouseMove;
 AssociatedObject.MouseLeftButtonUp +=AssociatedObject_MouseLeftButtonUp;
}
protected override void OnDetaching()  
{
 base.OnDetaching();
 AssociatedObject.MouseLeftButtonDown -= AssociatedObject_MouseLeftButtonDown;
 AssociatedObject.MouseMove -= AssociatedObject_MouseMove;
 AssociatedObject.MouseLeftButtonUp -= AssociatedObject_MouseLeftButtonUp;
}

Son adım olarak uygun kodları event handler’lara yazmak olacak.Örnek vermek gerekirse kullanıcı mosue’ın sol tuşuna bastığında behavior’ımız sürükleme işlemine başlar,elementin o an bulunduğu noktayı hesaplar.

private Canvas canvas;
private bool isDragging = false;
private Point mouseOffset;
void AssociatedObject_MouseLeftButtonUp(object sender, 
System.Windows.Input.MouseButtonEventArgs e)
 {
    if (isDragging)
     {
        AssociatedObject.ReleaseMouseCapture();
        isDragging = false;
     }
 }

void AssociatedObject_MouseMove(object sender, 
System.Windows. Input.MouseEventArgs e)
 {
    if (isDragging)
     {
       Point point = e.GetPosition(canvas);
       AssociatedObject.SetValue(Canvas.TopProperty, point.Y - mouseOffset.Y);
       AssociatedObject.SetValue(Canvas.LeftProperty, point.X - mouseOffset.X);
     }
}
void AssociatedObject_MouseLeftButtonDown(object sender, 
System.Windows.Input.MouseButtonEventArgs e)
{
  if (canvas==null)
   {
     canvas = VisualTreeHelper.GetParent(AssociatedObject) as Canvas;
     isDragging = true;
     mouseOffset = e.GetPosition(AssociatedObject);
     AssociatedObject.CaptureMouse();
   }
}

Artık bizde kendi behavior’ımızı oluşturmuş olduk hepsi bu kadar. Sıra geldi projemizde kullanmaya. Hemen yeni bir WPF  projesi oluşturup referans olarak oluşturmuş olduğumuz DragBehavior.dll ve System.Windows.Interactivity.dll dosyalarını ekleyelim. Daha sonra XAML tarafında aşağıdaki gibi yeni bir namespace ekleyerek behavior’ımızı kullanabiliriz: 

xmlns:local="clr-namespace:DragBehavior;assembly=DragBehavior"

 xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
<Canvas>
 <TextBlock Text="Test" FontSize="36">
   <i:Interaction.Behaviors>
     <local:DragBehaviour/>
   </i:Interaction.Behaviors>
 </TextBlock>
<Rectangle Fill="Brown" Width="50" Height="50" Canvas.Left="30" Canvas.Top="50">
   <i:Interaction.Behaviors>
      <local:DragBehaviour/>
   </i:Interaction.Behaviors>
</Rectangle>
</Canvas>

Gördüğünüz gibi kendi behavior’ımızı yazmak da kullanmak da bir o kadar kolay.İhtiyaçlarınız doğrultusunda başkalarının yazdığı ya da kendi yazdığınız behavior’larınızı tek bir dll dosyasında toplayarak kendi kütüphanelerinizi de oluşturabilirsiniz.

Kolay gelsin.

CustomBehaviorDemo.zip (48,86 kb)

About the Author