Bagikan melalui


Pewarisan nilai properti (WPF .NET)

Pewarisan nilai properti adalah fitur sistem properti Windows Presentation Foundation (WPF) dan berlaku untuk properti dependensi. Pewarisan nilai properti memungkinkan elemen turunan di pohon elemen mendapatkan nilai properti tertentu dari elemen induk terdekat. Karena elemen induk mungkin juga telah memperoleh nilai propertinya melalui pewarisan nilai properti, sistem berpotensi berulang kembali ke akar halaman.

Sistem properti WPF tidak mengaktifkan pewarisan nilai properti secara default, dan pewarisan nilai tidak aktif kecuali diaktifkan secara khusus dalam metadata properti dependensi. Bahkan dengan pewarisan nilai properti diaktifkan, elemen turunan hanya akan mewarisi nilai properti tanpa adanya nilai prioritas yang lebih tinggi.

Penting

Dokumentasi Panduan Desktop untuk .NET 7 dan .NET 6 sedang dibangun.

Prasyarat

Artikel ini mengasumsikan pengetahuan dasar tentang properti dependensi, dan bahwa Anda telah membaca gambaran umum properti Dependensi. Untuk mengikuti contoh dalam artikel ini, ini membantu jika Anda terbiasa dengan Extensible Application Markup Language (XAML) dan tahu cara menulis aplikasi WPF.

Warisan melalui pohon elemen

Pewarisan nilai properti bukan konsep yang sama dengan warisan kelas dalam pemrograman berorientasi objek, di mana kelas turunan mewarisi anggota kelas dasar. Warisan semacam itu juga aktif di WPF, meskipun di XAML properti kelas dasar yang diwariskan diekspos sebagai atribut elemen XAML yang mewakili kelas turunan.

Pewarisan nilai properti adalah mekanisme di mana nilai properti dependensi disebarluaskan dari elemen induk ke anak dalam pohon elemen yang berisi properti . Dalam markup XAML, pohon elemen terlihat sebagai elemen berlapis.

Contoh berikut menunjukkan elemen berlapis di XAML. WPF mendaftarkan AllowDrop properti dependensi pada UIElement kelas dengan metadata properti yang memungkinkan pewarisan nilai properti dan mengatur nilai default ke false. Properti AllowDrop dependensi ada pada Canvaselemen , StackPanel, dan Label karena semuanya berasal dari UIElement. AllowDrop Karena properti dependensi aktif diatur canvas1 ke true, turunan stackPanel1 dan label1 elemen mewarisi true sebagai nilainyaAllowDrop.

<Canvas x:Name="canvas1" Grid.Column="0" Margin="20" Background="Orange" AllowDrop="True">
    <StackPanel Name="stackPanel1" Margin="20" Background="Green">
        <Label Name="label1" Margin="20" Height="40" Width="40" Background="Blue"/>
    </StackPanel>
</Canvas>

Anda juga dapat membuat pohon elemen secara terprogram dengan menambahkan objek elemen ke kumpulan elemen turunan dari objek elemen lain. Pada run time, warisan nilai properti beroperasi pada pohon objek yang dihasilkan. Dalam contoh berikut, stackPanel2 ditambahkan ke kumpulan anak .canvas2 Demikian pula, label2 ditambahkan ke koleksi anak dari stackPanel2. AllowDrop Karena properti dependensi aktif diatur canvas2 ke true, turunan stackPanel2 dan label2 elemen mewarisi true sebagai nilainyaAllowDrop.

Canvas canvas2 = new()
{
    AllowDrop = true
};
StackPanel stackPanel2 = new();
Label label2 = new();
canvas2.Children.Add(stackPanel2);
stackPanel2.Children.Add(label2);
Dim canvas2 As New Canvas With {
    .AllowDrop = True
}
Dim stackPanel2 As New StackPanel()
Dim label2 As New Label()
canvas2.Children.Add(stackPanel2)
stackPanel2.Children.Add(label2)

Aplikasi praktis pewarisan nilai properti

Properti dependensi WPF tertentu memiliki pewarisan nilai yang diaktifkan secara default, seperti AllowDrop dan FlowDirection. Biasanya, properti dengan pewarisan nilai yang diaktifkan secara default diimplementasikan pada kelas elemen UI dasar, sehingga ada pada kelas turunan. Misalnya, karena AllowDrop diimplementasikan pada UIElement kelas dasar, properti dependensi tersebut juga ada pada setiap kontrol yang berasal dari UIElement. WPF memungkinkan pewarisan nilai pada properti dependensi yang nyaman bagi pengguna untuk mengatur nilai properti sekali pada elemen induk dan memiliki nilai properti yang disebarkan ke elemen turunan di pohon elemen.

Model pewarisan nilai properti menetapkan nilai properti, baik yang diwariskan maupun tidak diwariskan, sesuai dengan nilai properti dependensi yang diutamakan. Jadi, nilai properti elemen induk hanya akan diterapkan ke elemen anak, jika properti elemen turunan tidak memiliki nilai prioritas yang lebih tinggi, seperti nilai yang ditetapkan secara lokal, atau nilai yang diperoleh melalui gaya, templat, atau pengikatan data.

Properti FlowDirection dependensi mengatur arah tata letak elemen UI teks dan anak dalam elemen induk. Biasanya, Anda akan mengharapkan arah alur teks dan elemen UI dalam halaman konsisten. Karena pewarisan nilai diaktifkan dalam metadataFlowDirectionproperti , nilai hanya perlu diatur sekali di bagian atas pohon elemen untuk halaman. Dalam kasus yang jarang terjadi di mana campuran arah aliran ditujukan untuk halaman, arah alur yang berbeda dapat diatur pada elemen di pohon dengan menetapkan nilai yang ditetapkan secara lokal. Arah alur baru kemudian akan disebarkan ke elemen turunan di bawah tingkat tersebut.

Membuat properti kustom dapat diwariskan

Anda dapat membuat properti dependensi kustom dapat diwariskan dengan mengaktifkan properti dalam instans FrameworkPropertyMetadata, lalu mendaftarkan properti dependensi kustom Anda dengan instans metadata tersebutInherits. Secara default, Inherits diatur ke false dalam FrameworkPropertyMetadata. Membuat nilai properti yang dapat diwariskan memengaruhi performa, jadi hanya diatur Inherits ke true jika fitur tersebut diperlukan.

Saat Anda mendaftarkan properti dependensi dengan Inherits diaktifkan dalam metadata, gunakan RegisterAttached metode seperti yang dijelaskan dalam Mendaftarkan properti terlampir. Selain itu, tetapkan nilai default ke properti sehingga ada nilai yang dapat diwariskan. Anda mungkin juga ingin membuat pembungkus properti dengan get dan set aksesor pada jenis pemilik, seperti yang Anda lakukan untuk properti dependensi yang tidak terpasang. Dengan begitu Anda dapat mengatur nilai properti menggunakan pembungkus properti pada pemilik atau jenis turunan. Contoh berikut membuat properti dependensi bernama IsTransparent, dengan Inherits diaktifkan dan nilai falsedefault . Contohnya juga mencakup pembungkus properti dengan get dan set aksesor.

public class Canvas_IsTransparentInheritEnabled : Canvas
{
    // Register an attached dependency property with the specified
    // property name, property type, owner type, and property metadata
    // (default value is 'false' and property value inheritance is enabled).
    public static readonly DependencyProperty IsTransparentProperty =
        DependencyProperty.RegisterAttached(
            name: "IsTransparent",
            propertyType: typeof(bool),
            ownerType: typeof(Canvas_IsTransparentInheritEnabled),
            defaultMetadata: new FrameworkPropertyMetadata(
                defaultValue: false,
                flags: FrameworkPropertyMetadataOptions.Inherits));

    // Declare a get accessor method.
    public static bool GetIsTransparent(Canvas element)
    {
        return (bool)element.GetValue(IsTransparentProperty);
    }

    // Declare a set accessor method.
    public static void SetIsTransparent(Canvas element, bool value)
    {
        element.SetValue(IsTransparentProperty, value);
    }

    // For convenience, declare a property wrapper with get/set accessors.
    public bool IsTransparent
    {
        get => (bool)GetValue(IsTransparentProperty);
        set => SetValue(IsTransparentProperty, value);
    }
}
Public Class Canvas_IsTransparentInheritEnabled
    Inherits Canvas

    ' Register an attached dependency property with the specified
    ' property name, property type, owner type, and property metadata
    ' (default value is 'false' and property value inheritance is enabled).
    Public Shared ReadOnly IsTransparentProperty As DependencyProperty =
        DependencyProperty.RegisterAttached(
            name:="IsTransparent",
            propertyType:=GetType(Boolean),
            ownerType:=GetType(Canvas_IsTransparentInheritEnabled),
            defaultMetadata:=New FrameworkPropertyMetadata(
                defaultValue:=False,
                flags:=FrameworkPropertyMetadataOptions.[Inherits]))

    ' Declare a get accessor method.
    Public Shared Function GetIsTransparent(element As Canvas) As Boolean
        Return element.GetValue(IsTransparentProperty)
    End Function

    ' Declare a set accessor method.
    Public Shared Sub SetIsTransparent(element As Canvas, value As Boolean)
        element.SetValue(IsTransparentProperty, value)
    End Sub

    ' For convenience, declare a property wrapper with get/set accessors.
    Public Property IsTransparent As Boolean
        Get
            Return GetValue(IsTransparentProperty)
        End Get
        Set(value As Boolean)
            SetValue(IsTransparentProperty, value)
        End Set
    End Property
End Class

Properti terlampir secara konseptual mirip dengan properti global. Anda dapat memeriksa nilainya pada apa pun DependencyObject dan mendapatkan hasil yang valid. Skenario umum untuk properti terlampir adalah mengatur nilai properti pada elemen turunan, dan skenario tersebut lebih efektif jika properti yang dimaksud secara implisit ada sebagai properti terlampir pada setiap DependencyObject elemen di pohon.

Mewarisi nilai properti di seluruh batas pohon

Warisan properti bekerja dengan melintasi pohon elemen. Pohon ini sering sejajar dengan pohon logis. Namun, setiap kali Anda menyertakan objek tingkat inti WPF, seperti Brush, dalam markup yang mendefinisikan pohon elemen, Anda telah membuat pohon logis yang terhenti. Pohon logis sejati tidak secara konseptual diperluas melalui Brush, karena pohon logis adalah konsep tingkat kerangka kerja WPF. Anda dapat menggunakan metode pembantu LogicalTreeHelper untuk menganalisis dan melihat sejauh mana pohon logis. Pewarisan nilai properti dapat meneruskan nilai yang diwariskan melalui pohon logika yang dihentikan, tetapi hanya jika properti yang dapat diwariskan terdaftar sebagai properti terlampir dan tidak ada batas pemblokiran warisan yang dibatasi, seperti Frame.

Catatan

Meskipun pewarisan nilai properti mungkin tampak berfungsi untuk properti dependensi yang tidak terpasang, perilaku warisan untuk properti yang tidak terpasang melalui beberapa batas elemen di pohon runtime tidak terdefinisi. Setiap kali Anda menentukan Inherits dalam metadata properti, daftarkan properti Anda menggunakan RegisterAttached.

Baca juga