Giriş

WPF ile uğraştıysanız farkında olmadan da olsa mutlaka Dependency propertyleri kullanmışsınızdır.Dependency propertyler  normal .NET propertylerine oldukça benzemektedir, fakat Dependency propertyler konsept olarak çok daha güçlü ve komplekstir.Aralarındaki en önemli fark,normal bir  .NET propertynin değeri sınıfta tanımlanmış private bir üyeden direkt olarak okunur.

Bir dependency propertynin değeri ise GetValue() metodu çağrıldığında dinamik olarak çözümlenir.Bir dependency propertynin değerini set ettiğimizde bu nesnemizin bir alanında saklanmaz onun yerine DependencyObject temel sınıfı tarafından sağlanan bir dictionary de saklanmaktadır.Bildiğiniz gibi dictionary ler key ve value dan oluşmaktadır.Giriş key dediğimiz property ismi,value ise set etmek istediğimiz değeri tanımlamaktadır.

Dependency propertylerin avantajlarından en önemlileri bellek dağıtık kullanımını azaltma,değer kalıtımı ve property değişim bildirimi olarak sıralayabiliriz.Burada değer kalıtımı dediğimiz bir dependency propertye eriştiğimizde değeri, değer çözümleme stratejisi kullanılarak çözümlenir.Eğer lokal bir değer ayarlanmamışsa,dependency property bir değer buluncaya kadar mantıksal ağaçta bir üste yönlenir.Örneğin root elementte FontWeight’i ayarlarsak root element altındaki tüm TextBlock lara bu stili override etmediğimiz sürece uygulanacaktır.

Değer Çözümleme Stratejisi

Dependency property lere her erişimimizde değeri çözümlemek için yukardan aşağıya doğru öncelik sırasını takip eder.

1.Animation

2.Binding Expression

3.Local Value

4.Custom Style Trigger

5.Custom Template Trigger

6.Custom Style Setter

7.Default Style Trigger

8.Default Style Setter

9.Inherited Value

10.Default Value 

Her WPF kontrolü static DependencyProperty sınıfına bazı dependency property leri kayıt eder.Bu propertylerin her biri tekil bir key ‘e (anahtar) ve geridönüş ve varsayılan değer içeren metadata ya sahiptir.Dependency property kullanmak isteyen tüm tipler Dependency Object sınıfından kalıtılmış olmak zorundadır.Bir dependency property’e onun .NET property wrapper üzerinden eriştiğimizde , değere erişmek için GetValue() metodunu çağırır.Bu metod değer çözümleme stratejisini kullanarak uygun değeri döndürür.

Dependency Property Tanımlama

// Dependency Property        

 public static readonly DependencyProperty HasTextProperty =  DependencyProperty.Register("HasText", typeof(bool), typeof(MainWindow), new FrameworkPropertyMetadata(false));  

//.NET Property wrapper       

 public bool HasText       

{          

      get { return (bool)GetValue(HasTextProperty); }    

      set { SetValue(HasTextProperty, value); }      

}

Yukarıda tanımlanan dependency property ilk bakışta biraz karışık gelse de aslında çok kullanışlı ve güçlü bir yapısı vardır.Bir dependency property tanımlamak için isterseniz kısayol olarak code snippet kullanabilirsiniz.Kod tarafında propdp yazıp klavyeden  iki kere Tab tuşuna bastığınızda otomatik olarak bir dependency property tanımlanır.Buradan önemli bir nokta isimlendirmeye dikkat ettiyseniz sonu Property ile bitmektedir.Bu tanımlama için gerekli bir koşuldur.İsimlendirmenin sonuna Property kelimesi konulması gerekmektedir HasTextProperty gibi.

Her dependency property değişikliği bildirme,değeri zorlama ve doğrulama  için bir callback sağlar.

new FrameworkPropertyMetadata(false, OnHasTextPropertyChanged, OnCoerceHasTextProperty,OnValidateHasTextProperty);

Change Notification Callback Metodu

HasTextProperty’ sinin değeri her değiştiğinde çağrılır.Yeni değer EventArgs üzerinden geçirilir.

private static void OnHasTextPropertyChanged(DependencyObject source,DependencyPropertyChangedEventArgs e) {       

     MainWindow control = source as MainWindow;         

     bool val= (bool)e.NewValue;                   

 }

Coerce Value Callback Metodu

Coerce value callback,exception fırlatmadan değerin belirlenen sınırlar içerisinde olmasını ayarlamamızı sağlar.Mesela bir progress  bar’ı ele alırsak değerinin minimum 0 ve maximum 100 arasında olması için zorlayabiliriz.Böylece exception fırlatmasını da engellemiş oluruz.Aşağıdaki örnek kodda eğer değerimiz 0 ile 100 arasında değilse değerimizi  0 olarak atıyoruz.

private static object OnCoerceHasTextProperty(DependencyObject sender, object data)  
 {       
     if (!((int)data >= 0 && (int)data<=100))            
     {          
          data = 0;  
     }        
     return data;       
}

Validation Callback Metodu

Bu metodumuzda ise set edilen değerin bizim dependency property nesnemizin tipinde olup olmadığını doğrulamamızı sağlar.Eğer false dönerse ArgumentException fırlatılır.

private static bool OnValidateHasTextProperty(object data)  
{    
    return data is bool; 
}

Gördüğünüz gibi dependency property ‘leri kısaca bu şekilde tanımlayabiliriz.Normal .NET property’ler ile arasındaki farka gözattık ve bir dependency property tanımlama konusuna giriş yapmış olduk.Umarım yararlı bir yazı olmuştur.

Kolay gelsin.

About the Author