Share via


Koleksiyon türü bağımlılık özellikleri (WPF .NET)

Bu makalede, koleksiyon türü olan bir bağımlılık özelliğini uygulamak için rehberlik ve önerilen desenler sağlanır.

Önemli

.NET 7 ve .NET 6 için Masaüstü Kılavuzu belgeleri yapım aşamasındadır.

Ön koşullar

Makalede bağımlılık özellikleri hakkında temel bilgiler edindiğiniz ve Bağımlılık özelliklerine genel bakış makalesini okuduğunuz varsayılır. Bu makaledeki örnekleri takip etmek için Genişletilebilir Uygulama biçimlendirme dili (XAML) hakkında bilgi sahibi olmanız ve WPF uygulamalarının nasıl yazabileceğinizi bilmeniz yardımcı olur.

Koleksiyon türü bağımlılık özelliği uygulama

Genel olarak, bağımlılık özelliği için uygulama deseni, alan veya başka bir yapı yerine tanımlayıcı DependencyProperty tarafından yedeklenen bir CLR özellik sarmalayıcısıdır. Koleksiyon türü bağımlılık özelliğini uygularken aynı deseni izleyebilirsiniz. Koleksiyon öğesi türü bir veya türetilmiş bir DependencyObjectFreezable sınıfsa desen daha karmaşıktır.

Koleksiyonu başlatma

Bir bağımlılık özelliği oluşturduğunuzda, genellikle ilk özellik değerini belirtmek yerine bağımlılık özelliği meta verileri aracılığıyla varsayılan değeri belirtirsiniz. Ancak, özellik değeriniz bir başvuru türüyse, varsayılan değer bağımlılık özelliğini kaydeden sınıfın oluşturucusunda ayarlanmalıdır. Bağımlılık özelliği meta verileri varsayılan başvuru türü değerini içermemelidir çünkü bu değer sınıfın tüm örneklerine atanır ve tek bir sınıf oluşturulur.

Aşağıdaki örnek, genel List<T>bir Aquarium içindeki öğe koleksiyonunu FrameworkElement içeren bir sınıf bildirir. Yöntemine RegisterReadOnly(String, Type, Type, PropertyMetadata) geçirilen öğesine varsayılan bir koleksiyon değeri dahil PropertyMetadata değildir ve bunun yerine sınıf oluşturucu, varsayılan koleksiyon değerini yeni bir genel Listolarak ayarlamak için kullanılır.

public class Aquarium : DependencyObject
{
    // Register a dependency property with the specified property name,
    // property type, owner type, and property metadata.
    private static readonly DependencyPropertyKey s_aquariumContentsPropertyKey =
        DependencyProperty.RegisterReadOnly(
          name: "AquariumContents",
          propertyType: typeof(List<FrameworkElement>),
          ownerType: typeof(Aquarium),
          typeMetadata: new FrameworkPropertyMetadata()
          //typeMetadata: new FrameworkPropertyMetadata(new List<FrameworkElement>())
        );

    // Set the default collection value in a class constructor.
    public Aquarium() => SetValue(s_aquariumContentsPropertyKey, new List<FrameworkElement>());

    // Declare a public get accessor.
    public List<FrameworkElement> AquariumContents =>
        (List<FrameworkElement>)GetValue(s_aquariumContentsPropertyKey.DependencyProperty);
}

public class Fish : FrameworkElement { }
Public Class Aquarium
    Inherits DependencyObject

    ' Register a dependency property with the specified property name,
    ' property type, owner type, and property metadata.
    Private Shared ReadOnly s_aquariumContentsPropertyKey As DependencyPropertyKey =
        DependencyProperty.RegisterReadOnly(
            name:="AquariumContents",
            propertyType:=GetType(List(Of FrameworkElement)),
            ownerType:=GetType(Aquarium),
            typeMetadata:=New FrameworkPropertyMetadata())
            'typeMetadata:=New FrameworkPropertyMetadata(New List(Of FrameworkElement)))

    ' Set the default collection value in a class constructor.
    Public Sub New()
        SetValue(s_aquariumContentsPropertyKey, New List(Of FrameworkElement)())
    End Sub

    ' Declare a public get accessor.
    Public ReadOnly Property AquariumContents As List(Of FrameworkElement)
        Get
            Return CType(GetValue(s_aquariumContentsPropertyKey.DependencyProperty), List(Of FrameworkElement))
        End Get
    End Property
End Class

Public Class Fish
    Inherits FrameworkElement
End Class

Aşağıdaki test kodu iki ayrı Aquarium örneğin örneğini oluşturur ve her koleksiyona farklı Fish bir öğe ekler. Kodu çalıştırırsanız, her Aquarium örneğin beklendiği gibi tek bir koleksiyon öğesi olduğunu görürsünüz.

private void InitializeAquariums(object sender, RoutedEventArgs e)
{
    Aquarium aquarium1 = new();
    Aquarium aquarium2 = new();
    aquarium1.AquariumContents.Add(new Fish());
    aquarium2.AquariumContents.Add(new Fish());
    MessageBox.Show(
        $"aquarium1 contains {aquarium1.AquariumContents.Count} fish\r\n" +
        $"aquarium2 contains {aquarium2.AquariumContents.Count} fish");
}
Private Sub InitializeAquariums(sender As Object, e As RoutedEventArgs)
    Dim aquarium1 As New Aquarium()
    Dim aquarium2 As New Aquarium()
    aquarium1.AquariumContents.Add(New Fish())
    aquarium2.AquariumContents.Add(New Fish())
    MessageBox.Show($"aquarium1 contains {aquarium1.AquariumContents.Count} fish{Environment.NewLine}" +
                    $"aquarium2 contains {aquarium2.AquariumContents.Count} fish")
End Sub

Ancak, sınıf oluşturucusunun açıklamalarını çıkarır ve yöntemine RegisterReadOnly(String, Type, Type, PropertyMetadata) varsayılan PropertyMetadata koleksiyon değerini geçirirseniz, her Aquarium örneğin iki koleksiyon öğesi aldığını görürsünüz! Bunun nedeni, her iki örneğin de Fish Aquarium sınıfının tüm örnekleri tarafından paylaşılan aynı listeye eklenmesidir. Bu nedenle, amaç her nesne örneğinin kendi listesine sahip olması için olduğunda, varsayılan değer sınıf oluşturucusunda ayarlanmalıdır.

Okuma-yazma koleksiyonunu başlatma

Aşağıdaki örnek, ve anahtar olmayan imza yöntemlerini Register(String, Type, Type)SetValue(DependencyProperty, Object)kullanarak sınıfında okuma-yazma koleksiyon türü bağımlılık özelliğini Aquarium bildirir.

public class Aquarium : DependencyObject
{
    // Register a dependency property with the specified property name,
    // property type, and owner type. Store the dependency property
    // identifier as a public static readonly member of the class.
    public static readonly DependencyProperty AquariumContentsProperty =
        DependencyProperty.Register(
          name: "AquariumContents",
          propertyType: typeof(List<FrameworkElement>),
          ownerType: typeof(Aquarium)
        );

    // Set the default collection value in a class constructor.
    public Aquarium() => SetValue(AquariumContentsProperty, new List<FrameworkElement>());

    // Declare public get and set accessors.
    public List<FrameworkElement> AquariumContents
    {
        get => (List<FrameworkElement>)GetValue(AquariumContentsProperty);
        set => SetValue(AquariumContentsProperty, value);
    }
}
Public Class Aquarium
    Inherits DependencyObject

    ' Register a dependency property with the specified property name,
    ' property type, and owner type. Store the dependency property
    ' identifier as a static member of the class.
    Public Shared ReadOnly AquariumContentsProperty As DependencyProperty =
        DependencyProperty.Register(
            name:="AquariumContents",
            propertyType:=GetType(List(Of FrameworkElement)),
            ownerType:=GetType(Aquarium))

    ' Set the default collection value in a class constructor.
    Public Sub New()
        SetValue(AquariumContentsProperty, New List(Of FrameworkElement)())
    End Sub

    ' Declare public get and set accessors.
    Public Property AquariumContents As List(Of FrameworkElement)
        Get
            Return CType(GetValue(AquariumContentsProperty), List(Of FrameworkElement))
        End Get
        Set
            SetValue(AquariumContentsProperty, Value)
        End Set
    End Property
End Class

FreezableCollection bağımlılık özellikleri

Koleksiyon türü bağımlılık özelliği, alt özelliklerindeki değişiklikleri otomatik olarak raporlamaz. Sonuç olarak, bir koleksiyona bağlanıyorsanız, bağlama bazı veri bağlama senaryolarını geçersiz hale getirerek değişiklikleri bildirmeyebilir. Ancak bağımlılık özellik türü için kullanırsanız FreezableCollection<T> , koleksiyon öğelerinin özelliklerindeki değişiklikler düzgün şekilde bildirilir ve bağlama beklendiği gibi çalışır.

Bağımlılık nesneleri koleksiyonunda altözellik bağlamasını etkinleştirmek için, türetilmiş herhangi DependencyObject bir sınıfın tür kısıtlamasıyla koleksiyon türünü FreezableCollectionkullanın.

Aşağıdaki örnek, türü kısıtlaması FrameworkElementolan içeren FreezableCollection bir sınıf bildirirAquarium. Yöntemine RegisterReadOnly(String, Type, Type, PropertyMetadata) geçirilen öğesine varsayılan bir koleksiyon değeri dahil PropertyMetadata değildir ve bunun yerine sınıf oluşturucu, varsayılan koleksiyon değerini yeni FreezableCollectionolarak ayarlamak için kullanılır.

public class Aquarium : DependencyObject
{
    // Register a dependency property with the specified property name,
    // property type, and owner type.
    private static readonly DependencyPropertyKey s_aquariumContentsPropertyKey =
        DependencyProperty.RegisterReadOnly(
          name: "AquariumContents",
          propertyType: typeof(FreezableCollection<FrameworkElement>),
          ownerType: typeof(Aquarium),
          typeMetadata: new FrameworkPropertyMetadata()
        );

    // Store the dependency property identifier as a static member of the class.
    public static readonly DependencyProperty AquariumContentsProperty =
        s_aquariumContentsPropertyKey.DependencyProperty;

    // Set the default collection value in a class constructor.
    public Aquarium() => SetValue(s_aquariumContentsPropertyKey, new FreezableCollection<FrameworkElement>());

    // Declare a public get accessor.
    public FreezableCollection<FrameworkElement> AquariumContents =>
        (FreezableCollection<FrameworkElement>)GetValue(AquariumContentsProperty);
}
Public Class Aquarium
    Inherits DependencyObject

    ' Register a dependency property with the specified property name,
    ' property type, and owner type.
    Private Shared ReadOnly s_aquariumContentsPropertyKey As DependencyPropertyKey =
        DependencyProperty.RegisterReadOnly(
            name:="AquariumContents",
            propertyType:=GetType(FreezableCollection(Of FrameworkElement)),
            ownerType:=GetType(Aquarium),
            typeMetadata:=New FrameworkPropertyMetadata())

    ' Set the default collection value in a class constructor.
    Public Sub New()
        SetValue(s_aquariumContentsPropertyKey, New FreezableCollection(Of FrameworkElement)())
    End Sub

    ' Declare a public get accessor.
    Public ReadOnly Property AquariumContents As FreezableCollection(Of FrameworkElement)
        Get
            Return CType(GetValue(s_aquariumContentsPropertyKey.DependencyProperty), FreezableCollection(Of FrameworkElement))
        End Get
    End Property
End Class

Ayrıca bkz.