Koleksiyon Türü Bağımlılık Özellikleri
Bu konu başlığında, özelliğin türünün koleksiyon türü olduğu bir bağımlılık özelliğinin nasıl uygulanacağı konusunda rehberlik ve önerilen desenler sağlanır.
Koleksiyon Türü Bağımlılık Özelliği Uygulama
Genel olarak bir bağımlılık özelliği için, izlediğiniz uygulama deseni, bir CLR özellik sarmalayıcısı tanımlamanızdır; burada bu özellik bir alan veya başka bir yapı yerine bir DependencyProperty tanımlayıcı tarafından yedeklenmiştir. Koleksiyon türü özelliği uygularken de aynı deseni izlersiniz. Ancak koleksiyon türü özelliği, koleksiyon içinde yer alan türün kendisi veya Freezable türetilmiş bir DependencyObject sınıf olduğunda desene biraz karmaşıklık ekler.
Koleksiyonu Varsayılan Değerin Ötesinde Başlatma
Bağımlılık özelliği oluşturduğunuzda, özellik varsayılan değerini ilk alan değeri olarak belirtmezsiniz. Bunun yerine, bağımlılık özelliği meta verileri aracılığıyla varsayılan değeri belirtirsiniz. Özelliğiniz bir başvuru türüyse, bağımlılık özelliği meta verilerinde belirtilen varsayılan değer örnek başına varsayılan bir değer değildir; bunun yerine, türün tüm örnekleri için geçerli olan varsayılan bir değerdir. Bu nedenle, koleksiyon özelliği meta verileri tarafından tanımlanan tekil statik koleksiyonu, türünüzün yeni oluşturulan örnekleri için çalışan varsayılan değer olarak kullanmamaya dikkat etmeniz gerekir. Bunun yerine, koleksiyon değerini sınıf oluşturucu mantığınızın bir parçası olarak özellikle benzersiz (örnek) bir koleksiyona ayarladığınızdan emin olmanız gerekir. Aksi takdirde, kasıtsız bir tekil sınıf oluşturmuş olursunuz.
Aşağıdaki örneği inceleyin. Örneğin aşağıdaki bölümünde, varsayılan değere sahip bir kusur içeren bir sınıfın Aquarium
tanımı gösterilir. sınıfı, bir tür kısıtlaması ile FrameworkElement genel List<T> türü kullanan koleksiyon türü bağımlılık özelliğini AquariumObjects
tanımlar. Register(String, Type, Type, PropertyMetadata) Bağımlılık özelliğinin çağrısında meta veriler varsayılan değeri yeni bir genel List<T>olacak şekilde oluşturur.
Uyarı
Aşağıdaki kod doğru şekilde davranmıyor.
public class Fish : FrameworkElement { }
public class Aquarium : DependencyObject {
private static readonly DependencyPropertyKey AquariumContentsPropertyKey =
DependencyProperty.RegisterReadOnly(
"AquariumContents",
typeof(List<FrameworkElement>),
typeof(Aquarium),
new FrameworkPropertyMetadata(new List<FrameworkElement>())
);
public static readonly DependencyProperty AquariumContentsProperty =
AquariumContentsPropertyKey.DependencyProperty;
public List<FrameworkElement> AquariumContents
{
get { return (List<FrameworkElement>)GetValue(AquariumContentsProperty); }
}
// ...
}
Public Class Fish
Inherits FrameworkElement
End Class
Public Class Aquarium
Inherits DependencyObject
Private Shared ReadOnly AquariumContentsPropertyKey As DependencyPropertyKey = DependencyProperty.RegisterReadOnly("AquariumContents", GetType(List(Of FrameworkElement)), GetType(Aquarium), New FrameworkPropertyMetadata(New List(Of FrameworkElement)()))
Public Shared ReadOnly AquariumContentsProperty As DependencyProperty = AquariumContentsPropertyKey.DependencyProperty
Public ReadOnly Property AquariumContents() As List(Of FrameworkElement)
Get
Return CType(GetValue(AquariumContentsProperty), List(Of FrameworkElement))
End Get
End Property
' ...
End Class
Ancak, kodu gösterildiği gibi bıraktıysanız, bu tek liste varsayılan değeri tüm örnekleri Aquarium
için paylaşılır. İki ayrı Aquarium
örneğin örneğini nasıl oluşturabileceğinizi ve her birine tek bir farklı Fish
örneği nasıl ekleyebileceğinizi gösteren aşağıdaki test kodunu çalıştırdıysanız, şaşırtıcı bir sonuç görürsünüz:
Aquarium myAq1 = new Aquarium();
Aquarium myAq2 = new Aquarium();
Fish f1 = new Fish();
Fish f2 = new Fish();
myAq1.AquariumContents.Add(f1);
myAq2.AquariumContents.Add(f2);
MessageBox.Show("aq1 contains " + myAq1.AquariumContents.Count.ToString() + " things");
MessageBox.Show("aq2 contains " + myAq2.AquariumContents.Count.ToString() + " things");
Dim myAq1 As New Aquarium()
Dim myAq2 As New Aquarium()
Dim f1 As New Fish()
Dim f2 As New Fish()
myAq1.AquariumContents.Add(f1)
myAq2.AquariumContents.Add(f2)
MessageBox.Show("aq1 contains " & myAq1.AquariumContents.Count.ToString() & " things")
MessageBox.Show("aq2 contains " & myAq2.AquariumContents.Count.ToString() & " things")
Her koleksiyonun bir sayısı yerine, her koleksiyonun iki sayısı vardır! Bunun nedeni, her Aquarium
birinin varsayılan değer koleksiyonuna Fish
eklenmesidir. Bu, meta verilerdeki tek bir oluşturucu çağrısından kaynaklanır ve bu nedenle tüm örnekler arasında paylaşılır. Bu durum neredeyse hiç istediğiniz gibi değil.
Bu sorunu düzeltmek için koleksiyon bağımlılığı özellik değerini sınıf oluşturucu çağrısının bir parçası olarak benzersiz bir örneğe sıfırlamanız gerekir. özelliği salt okunur bir bağımlılık özelliği olduğundan, yalnızca sınıfı içinde erişilebilir olan öğesini kullanarak DependencyPropertyKey bunu ayarlamak için yöntemini kullanırsınızSetValue(DependencyPropertyKey, Object).
public Aquarium() : base()
{
SetValue(AquariumContentsPropertyKey, new List<FrameworkElement>());
}
Public Sub New()
MyBase.New()
SetValue(AquariumContentsPropertyKey, New List(Of FrameworkElement)())
End Sub
Şimdi, aynı test kodunu yeniden çalıştırdıysanız, her Aquarium
birinin kendi benzersiz koleksiyonunu desteklediği daha fazla beklenen sonuç görebilirsiniz.
Koleksiyon özelliğinizin okuma-yazma olmasını seçerseniz bu düzende küçük bir çeşitleme olacaktır. Bu durumda, başlatmayı yapmak için oluşturucudan ortak küme erişimcisini çağırabilirsiniz. Bu, ortak tanımlayıcı DependencyProperty kullanarak küme sarmalayıcınızın içindeki anahtar olmayan imzasını SetValue(DependencyProperty, Object) çağırmaya devam eder.
Koleksiyon Özelliklerinden Bağlama Değeri Değişikliklerini Raporlama
Kendisi bağımlılık özelliği olan bir koleksiyon özelliği, değişiklikleri otomatik olarak alt özelliklerine raporlamaz. Bir koleksiyonda bağlamalar oluşturuyorsanız bu, bağlamanın değişiklikleri raporlamasını önleyerek bazı veri bağlama senaryolarını geçersiz kılar. Ancak koleksiyon türünü koleksiyon türünüz FreezableCollection<T> olarak kullanırsanız, koleksiyondaki kapsanan öğelere yapılan alt özellik değişiklikleri düzgün şekilde bildirilir ve bağlama beklendiği gibi çalışır.
Bağımlılık nesnesi koleksiyonunda alt özellik bağlamasını etkinleştirmek için, koleksiyon özelliğini tür FreezableCollection<T>olarak oluşturun ve bu koleksiyon için türetilmiş herhangi DependencyObject bir sınıfa yönelik bir tür kısıtlaması oluşturun.
Ayrıca bkz.
.NET Desktop feedback
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin