Bir (özel) bağımlılık özelliği ile WPF'de eklenmiş bir özellik arasındaki fark nedir? Her birinin kullanım alanları nelerdir? Uygulamalar tipik olarak nasıl farklılık gösterir?
Yanıtlar:
Konuyla ilgili çok az veya hiç belge bulmadığım için, kaynak kodun etrafından dolaşmak biraz zaman aldı , ama işte bir cevap.
Bir bağımlılık özelliğini normal ve ekli bir özellik olarak kaydetmek arasında, "felsefi" bir özellik dışında bir fark vardır ( normal özelliklerin bildirim türü ve türetme türleri tarafından kullanılması amaçlanmıştır, ekli özelliklerin şu şekilde kullanılması amaçlanmıştır: rastgele DependencyObject
örneklerdeki uzantılar ). "Felsefi", çünkü @MarqueIV'in @ ReedCopsey'in cevabına yaptığı yorumda fark ettiği gibi, normal özellikler rastgele DependencyObject
örneklerle de kullanılabilir .
Dahası, ekli özelliğin "bağımlılık özelliği türü" olduğunu belirten diğer yanıtlara katılmıyorum, çünkü yanıltıcıdır - bağımlılık özelliklerinin "türü" yoktur. Çerçeve, mülkün ekli olarak kaydedilip kaydedilmediğini umursamıyor - belirlemek bile mümkün değil (bu bilginin kayda geçirilmemesi anlamında, çünkü alakasız). Aslında, tüm özellikler iliştirilmiş mülklermiş gibi kaydedilir, ancak normal olanlar durumunda davranışlarını biraz değiştiren bazı ek şeyler yapılır.
Sizi kaynak kodundan kendi başınıza geçme zahmetinden kurtarmak için, burada olanların özetlenmiş bir versiyonu var.
Meta veriler belirtilmeden bir mülkü kaydederken, arama
DependencyProperty.Register(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass))
arama ile tam olarak aynı sonucu verir
DependencyProperty.RegisterAttached(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass))
Ancak, meta verileri belirtirken arama
DependencyProperty.Register(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass),
typeMetadata: new FrameworkPropertyMetadata
{
CoerceValueCallback = CoerceCallback,
DefaultValue = "default value",
PropertyChangedCallback = ChangedCallback
});
aramaya eşdeğerdir
var property = DependencyProperty.RegisterAttached(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass),
defaultMetadata: new PropertyMetadata
{
DefaultValue = "default value",
});
property.OverrideMetadata(
forType: typeof(MyClass),
typeMetadata: new FrameworkPropertyMetadata
{
CoerceValueCallback = CoerceCallback,
DefaultValue = "default value",
PropertyChangedCallback = ChangedCallback
});
Normal ve ekli bağımlılık özellikleri arasındaki temel (ve tek) fark, DependencyProperty.DefaultMetadata özelliği aracılığıyla kullanılabilen varsayılan meta verilerdir . Bu, Açıklamalar bölümünde bile bahsedilmektedir :
Eklenmemiş özellikler için, bu özellik tarafından döndürülen meta veri türü , özellik başlangıçta türetilmiş bir meta veri türüyle kaydedilmiş olsa bile, türetilmiş PropertyMetadata türü türlerine dönüştürülemez . Orijinal muhtemelen türetilmiş meta veri türü dahil olmak üzere orijinal olarak kaydedilmiş meta verileri istiyorsanız, bunun yerine GetMetadata (Tür) öğesini çağırın ve orijinal kayıt türünü bir parametre olarak iletin .
Ekli özellikler için, bu özellik tarafından döndürülen meta verilerin türü, orijinal RegisterAttached kayıt yönteminde verilen türle eşleşecektir .
Bu, sağlanan kodda açıkça görülebilir. Kayıt yöntemlerinde küçük ipuçları da gizlidir, yani RegisterAttached
metadata parametresi adlandırılır defaultMetadata
, oysa Register
bunun için adlandırılır typeMetadata
. Ekli özellikler için sağlanan meta veriler varsayılan meta veriler haline gelir. Bununla birlikte, normal özellikler durumunda, varsayılan meta veriler her zaman PropertyMetadata
yalnızca DefaultValue
ayarlanmış (sağlanan meta verilerden veya otomatik olarak) yeni bir örneğidir . Yalnızca sonraki çağrı OverrideMetadata
gerçekten sağlanan meta verileri kullanır.
Temel pratik fark, normal mülkler durumunda CoerceValueCallback
ve yalnızca sahip türü olarak bildirilen türden türetilen türler için PropertyChangedCallback
geçerli olması ve ekli mülkler için tüm türler için geçerli olmasıdır . Örneğin bu senaryoda:
var d = new DependencyObject();
d.SetValue(SomeClass.SomeProperty, "some value");
Kayıtlı PropertyChangedCallback
adı verilecek mülkiyet iliştirilmiş bir özellik olarak tescil edilmiş ise, ancak denilen olmayacak düzenli özelliği olarak kaydedildi eğer. Aynı şey geçerli CoerceValueCallback
.
İkincil bir fark OverrideMetadata
, sağlanan türün türetilmesini gerektiren olgudan kaynaklanır DependencyObject
. Pratikte, normal özellikleri için sahibi tipi anlamına gelir türetilmelidir gelen DependencyObject
olabilir ekli özellikleri için ise, herhangi bir (statik sınıflar, yapılar, enums, temsilciler, vs. dahil olmak üzere) tipi.
MarqueIV önerisi @ yanında çeşitli vesilelerle ben düzenli ve ekli özellikleri bunlar kullanılabilecek şekilde farklılık gösterdiğini görüşleri rastlamak ettik XAML . Yani, normal özellikler, ekli özelliklerin gerektirdiği açık ad sözdiziminin tersine örtük ad sözdizimi gerektirir. Bu teknik olarak doğru değildir , ancak pratikte genellikle böyledir. Açıklık için:
<!-- Implicit property name -->
<ns:SomeClass SomeProperty="some value" />
<!-- Explicit property name -->
<DependencyObject ns:SomeClass.SomeProperty="some value" />
Gelen saf XAML , bu sözdizimlerinden kullanımını düzenleyen tek kuralları aşağıdaki gibidir:
Bu koşulların sağlanması, destek bağımlılığı özelliğinin normal veya ekli olarak kaydedilmiş olup olmadığına bakılmaksızın, karşılık gelen sözdizimini kullanmanıza olanak tanır.
Şimdi, bahsedilen yanlış kanı, öğreticilerin büyük çoğunluğunun (stok Visual Studio kod parçacıklarıyla birlikte) , normal bağımlılık özellikleri için CLR özelliğini ve ekli olanlar için erişimcileri al / ayarlamanızı gerektirdiği gerçeğinden kaynaklanmaktadır . Ancak ikisini de aynı anda kullanmaktan sizi alıkoyan hiçbir şey yoktur, bu da tercih ettiğiniz sözdizimini kullanmanıza izin verir.
Ekli özellikler bir tür bağımlılık özelliğidir. Aradaki fark, nasıl kullanıldıklarında.
Ekli bir özellik ile özellik, kullanıldığı sınıfla aynı olmayan bir sınıf üzerinde tanımlanır. Bu genellikle düzen için kullanılır. İyi örnekler Panel.ZIndex veya Grid.Row'dur - bunu bir kontrole uygularsınız (yani: Button), ancak aslında Panel veya Grid'de tanımlanır. Özellik, düğme örneğine "eklenir".
Bu, örneğin bir konteynerin herhangi bir UIelement üzerinde kullanılabilecek özellikler oluşturmasına izin verir.
Uygulama farklılıklarına gelince - temelde özelliği tanımlarken Register ve RegisterAttached arasındaki farkı kullanma meselesidir.
Ekli özellikler temelde kap öğeleri içindir. Bir ızgaranız ve grid.row'unuz varsa, şimdi bu bir ızgara öğesinin ekli özelliği olarak kabul edilir. Ayrıca bu özelliği texbox, button vb. ızgaraya yerleştirin.
Bağımlılık özelliği, temelde başka bir sınıfa ait olan ve başka bir sınıfta kullanılan nitelik gibidir. örneğin: burada bir dikdörtgene sahip olduğunuz gibi, yükseklik ve genişlik dikdörtgenin normal özellikleridir, ancak Canvass sınıfına ait olduğu için sol ve üst bağımlılık özelliğidir.
Ekli özellikler, özel bir DependencyProperties türüdür. Bu değer hakkında hiçbir şey bilmeyen bir nesneye bir değer eklemenize izin verirler. Bu konsept için iyi bir örnek, yerleşim panelleridir. Her düzen panelinin, alt öğelerini hizalamak için farklı verilere ihtiyacı vardır. Canvas'ın Yukarı ve Sola, DockPanel'in Dock'a vb. İhtiyacı vardır. Kendi düzen panelinizi yazabileceğiniz için liste sonsuzdur. Gördüğünüz gibi, tüm bu özelliklere tüm WPF kontrollerinde sahip olmak mümkün değildir. Çözüm, ekli özelliklerdir. Belirli bir bağlamda başka bir kontrolden gelen verilere ihtiyaç duyan kontrol tarafından tanımlanırlar. Örneğin, bir ana mizanpaj paneli ile hizalanan bir öğe.
Ekli özelliği sınıfın kendisinde tanımlayabileceğinizi veya başka bir sınıfta tanımlayabileceğinizi düşünüyorum. Standart microsoft denetimlerini genişletmek için her zaman ekli özelliği kullanabiliriz. Ancak bağımlılık özelliğini kendi özel kontrolünüzde tanımlarsınız. Örneğin, kontrolünüzü standart bir kontrolden devralabilir ve kendi kontrolünüzde bir bağımlılık özelliği tanımlayabilir ve onu kullanabilirsiniz. Bu, ekli bir özelliği tanımlamaya ve bu ekli özelliği standart denetimde kullanmaya eşdeğerdir.