Bagikan melalui


Gambaran umum properti dependensi

Windows Presentation Foundation (WPF) menyediakan serangkaian layanan yang dapat digunakan untuk memperluas fungsionalitas dari suatu jenis properti . Secara kolektif, layanan ini disebut sebagai sistem properti WPF. Properti yang didukung oleh sistem properti WPF dikenal sebagai properti dependensi. Gambaran umum ini menjelaskan sistem properti WPF dan kemampuan properti dependensi, termasuk cara menggunakan properti dependensi yang ada di XAML dan dalam kode. Gambaran umum ini juga memperkenalkan aspek khusus properti dependensi, seperti metadata properti dependensi, dan cara membuat properti dependensi Anda sendiri di kelas kustom.

Prasyarat

Artikel ini mengasumsikan pengetahuan dasar tentang sistem jenis .NET dan pemrograman berorientasi objek. Untuk mengikuti contoh dalam artikel ini, ini membantu memahami XAML dan tahu cara menulis aplikasi WPF. Untuk informasi selengkapnya, lihat Tutorial : Membuat aplikasi WPF baru dengan .NET.

Properti dependensi dan properti CLR

Properti WPF biasanya diekspos sebagai properti .NET yang standar. Anda mungkin berinteraksi dengan properti ini pada tingkat dasar dan tidak pernah tahu bahwa properti tersebut diimplementasikan sebagai properti dependensi. Namun, keakraban dengan beberapa atau semua fitur sistem properti WPF, akan membantu Anda memanfaatkan fitur-fitur tersebut.

Tujuan properti dependensi adalah untuk memberikan cara untuk menghitung nilai properti berdasarkan nilai input lain, seperti:

  • Properti sistem, seperti tema dan preferensi pengguna.
  • Mekanisme penentuan properti just-in-time, seperti pengikatan data dan animasi/papan cerita.
  • Template serbaguna, seperti sumber daya dan gaya.
  • Nilai yang diketahui melalui hubungan induk-turunan dengan elemen lain di pohon elemen.

Selain itu, properti dependensi dapat menyediakan:

  • Validasi mandiri.
  • Nilai bawaan.
  • Panggilan balik yang memantau perubahan pada properti lain.
  • Sistem yang dapat memaksa nilai properti berdasarkan informasi runtime.

Kelas turunan dapat mengubah beberapa karakteristik properti yang ada dengan mengambil alih metadata properti dependensi, daripada mengesampingkan implementasi aktual properti yang ada atau membuat properti baru.

Di referensi SDK, Anda dapat mengidentifikasi properti dependensi dengan adanya bagian Informasi Properti Dependensi di halaman referensi terkelola untuk properti tersebut. Bagian Informasi Properti Dependensi menyertakan tautan ke bidang pengidentifikasi DependencyProperty untuk properti dependensi tersebut. Ini juga mencakup daftar opsi metadata untuk properti tersebut, informasi penimpaan per kelas, dan detail lainnya.

Properti dependensi mendukung properti CLR

Properti dependensi dan sistem properti WPF memperluas fungsionalitas properti dengan menyediakan jenis yang mendukung properti, sebagai alternatif untuk pola standar mendukung properti dengan bidang privat. Nama jenis ini DependencyProperty. Jenis penting lainnya yang mendefinisikan sistem properti WPF adalah DependencyObject, yang menentukan kelas dasar yang dapat mendaftar dan memiliki properti dependensi.

Berikut adalah beberapa terminologi yang umum digunakan:

  • properti ketergantungan, yang merupakan properti yang disokong oleh DependencyProperty.

  • pengidentifikasi Properti Dependensi, yang merupakan instans DependencyProperty yang diperoleh sebagai nilai pengembalian ketika mendaftarkan Properti Dependensi, kemudian disimpan sebagai anggota statis dari sebuah kelas. Banyak API yang berinteraksi dengan sistem properti WPF menggunakan pengidentifikasi properti dependensi sebagai parameter.

  • clr "wrapper", yang merupakan implementasi get dan set untuk properti. Implementasi ini menggabungkan pengidentifikasi properti dependensi dengan menggunakannya dalam panggilan GetValue dan SetValue. Dengan cara ini, sistem properti WPF menyediakan dukungan untuk properti.

Contoh berikut mendefinisikan properti ketergantungan IsSpinning untuk menunjukkan hubungan identifikasi DependencyProperty dengan properti yang didukungnya.

public static readonly DependencyProperty IsSpinningProperty = DependencyProperty.Register(
    "IsSpinning", typeof(bool),
    typeof(MainWindow)
    );

public bool IsSpinning
{
    get => (bool)GetValue(IsSpinningProperty);
    set => SetValue(IsSpinningProperty, value);
}
Public Shared ReadOnly IsSpinningProperty As DependencyProperty =
    DependencyProperty.Register("IsSpinning", GetType(Boolean), GetType(MainWindow))

Public Property IsSpinning As Boolean
    Get
        Return GetValue(IsSpinningProperty)
    End Get
    Set(value As Boolean)
        SetValue(IsSpinningProperty, value)
    End Set
End Property

Konvensi penamaan properti dan bidang pendukung DependencyProperty-nya penting. Nama bidang selalu merupakan nama properti, dengan akhiran Property yang ditambahkan. Untuk informasi selengkapnya tentang konvensi ini dan alasannya, lihat Properti dependensi kustom.

Mengatur nilai properti

Anda dapat mengatur properti baik dalam kode atau di XAML.

Mengatur nilai properti di XAML

Contoh XAML berikut mengatur warna latar belakang tombol menjadi merah. Nilai string untuk atribut XAML dikonversi tipe oleh pengurai WPF XAML menjadi tipe WPF. Dalam kode yang dihasilkan, jenis WPF adalah Color, melalui SolidColorBrush.

<Button Content="I am red" Background="Red"/>

XAML mendukung beberapa formulir sintaks untuk mengatur properti. Sintaks mana yang digunakan untuk properti tertentu tergantung pada jenis nilai yang digunakan properti, dan faktor lain, seperti keberadaan pengonversi jenis. Untuk informasi selengkapnya tentang sintaks XAML untuk mengatur properti, lihat XAML dalam sintaks WPF dan XAML Secara rinci

Contoh XAML berikut menunjukkan latar belakang tombol lain yang menggunakan sintaks elemen properti alih-alih sintaks atribut. Daripada mengatur warna solid sederhana, XAML mengatur properti tombol Background ke gambar. Elemen mewakili gambar tersebut, dan atribut elemen berlapis menentukan sumber gambar.

<Button Content="I have an image background">
    <Button.Background>
        <ImageBrush ImageSource="stripes.jpg"/>
    </Button.Background>
</Button>

Mengatur properti dalam kode

Mengatur nilai properti dependensi dalam kode biasanya hanya memanggil implementasi set yang ditampilkan oleh "lapisan" CLR.

Button myButton = new();
myButton.Width = 200.0;
Dim myButton As New Button With {
    .Width = 200.0
}

Mendapatkan nilai properti pada dasarnya merupakan sebuah panggilan ke implementasi "wrapper" get:

double whatWidth = myButton.Width;
Dim whatWidth As Double = myButton.Width

Anda juga dapat memanggil API sistem properti GetValue dan SetValue secara langsung. Memanggil API secara langsung sesuai untuk beberapa skenario, tetapi biasanya tidak saat Anda menggunakan properti yang ada. Biasanya, pembungkus lebih nyaman, dan memberikan paparan properti yang lebih baik untuk alat pengembang.

Properti dapat juga ditetapkan di XAML dan kemudian diakses dalam kode melalui code-behind. Untuk detailnya, lihat Code-behind dan XAML di WPF

Fungsionalitas properti yang disediakan oleh properti dependensi

Tidak seperti properti yang didukung oleh lapangan, properti dependensi memperluas fungsionalitas dari sebuah properti. Seringkali, fungsionalitas yang ditambahkan mewakili atau mendukung salah satu fitur ini:

Sumber Daya

Anda dapat mengatur nilai properti dependensi dengan mereferensikan sumber daya. Sumber daya biasanya ditentukan sebagai nilai properti Resources dari elemen akar halaman, atau aplikasi, karena lokasi ini menawarkan akses mudah ke sumber daya. Dalam contoh ini, kami menentukan sumber daya SolidColorBrush:

<StackPanel.Resources>
    <SolidColorBrush x:Key="MyBrush" Color="Gold"/>
</StackPanel.Resources>

Sekarang setelah sumber daya ditentukan, kita dapat mereferensikan sumber daya untuk memberikan nilai untuk properti Background:

<Button Background="{DynamicResource MyBrush}" Content="I am gold" />

Di WPF XAML, Anda dapat menggunakan referensi sumber daya statis atau dinamis. Sumber daya khusus ini direferensikan sebagai DynamicResource

Nota

Sumber daya diperlakukan sebagai nilai lokal, yang berarti bahwa jika Anda menetapkan nilai lokal lain, Anda akan menghilangkan referensi sumber daya. Untuk informasi selengkapnya, lihat pendahuluan nilai properti Dependensi.

Pengikatan data

Properti dependensi dapat mereferensikan nilai melalui pengikatan data. Pengikatan data berfungsi melalui sintaks ekstensi markup tertentu di XAML, atau objek Binding dalam kode. Dengan pengikatan data, penentuan nilai properti akhir ditangguhkan hingga waktu eksekusi, saat itu nilai tersebut diperoleh dari sumber data.

Contoh berikut mengatur properti Content untuk Button, dengan menggunakan pengikatan yang dideklarasikan dalam XAML. Pengikatan menggunakan konteks data yang diwariskan dan sumber data XmlDataProvider (tidak ditampilkan). Pengikatan itu sendiri menentukan properti sumber dalam sumber data dengan XPath.

<Button Content="{Binding Source={StaticResource TestData}, XPath=test[1]/@text}"/>

Nota

Pengikatan diperlakukan sebagai nilai lokal, yang berarti bahwa jika Anda menetapkan nilai lokal lain, Anda akan menghilangkan pengikatan. Untuk detailnya, lihat urutan nilai properti dependensi .

Properti dependensi, atau kelas DependencyObject, tidak secara asli mendukung INotifyPropertyChanged untuk pemberitahuan perubahan nilai properti sumber DependencyObject untuk operasi pengikatan data. Untuk informasi selengkapnya tentang cara membuat properti untuk digunakan dalam pengikatan data yang dapat melaporkan perubahan pada target pengikatan data, lihat Gambaran umum pengikatan data

Gaya

Gaya dan templat adalah alasan kuat untuk menggunakan properti dependensi. Gaya sangat berguna untuk mengatur properti yang menentukan UI aplikasi. Gaya biasanya didefinisikan sebagai sumber daya di XAML. Gaya berinteraksi dengan sistem properti karena biasanya berisi "setter" untuk properti tertentu, dan "pemicu" yang mengubah nilai properti berdasarkan nilai runtime untuk properti lain.

Contoh berikut membuat gaya sederhana, yang akan didefinisikan di dalam kamus Resources (tidak ditampilkan). Kemudian gaya tersebut diterapkan langsung ke properti Style untuk Button. Pengatur di dalam gaya mengubah properti Background untuk Button bergaya menjadi hijau.

<Style x:Key="GreenButtonStyle">
    <Setter Property="Control.Background" Value="Green"/>
</Style>
<Button Style="{StaticResource GreenButtonStyle}" Content="I am green"/>

Untuk informasi selengkapnya, lihat Gaya dan templat.

Animasi

Properti dependensi dapat dianimasikan. Saat animasi yang diterapkan berjalan, nilai animasi memiliki prioritas yang lebih tinggi daripada nilai properti lainnya, termasuk nilai lokal.

Contoh berikut menganimasikan properti Background dari Button. Secara teknis, sintaks elemen properti menetapkan SolidColorBrush kosong sebagai Background, dan properti Color dari SolidColorBrush dianimasikan.

<Button Content="I am animated">
    <Button.Background>
        <SolidColorBrush x:Name="AnimBrush"/>
    </Button.Background>
    <Button.Triggers>
        <EventTrigger RoutedEvent="FrameworkElement.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <ColorAnimation
                        Storyboard.TargetName="AnimBrush" 
                        Storyboard.TargetProperty="(SolidColorBrush.Color)"
                        From="Blue" To="White" Duration="0:0:1" 
                        AutoReverse="True" RepeatBehavior="Forever" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Button.Triggers>
</Button>

Untuk informasi selengkapnya tentang menganimasikan properti, lihat Gambaran umum Animasi dan Gambaran umum Storyboard

Penggantian metadata

Anda dapat mengubah perilaku tertentu dari properti dependensi dengan mengesampingkan metadatanya ketika Anda berasal dari kelas yang awalnya mendaftarkan properti dependensi. Menimpa metadata bergantung pada pengidentifikasi DependencyProperty dan tidak memerlukan mengimplementasi ulang properti. Perubahan metadata ditangani secara asli oleh sistem properti. Setiap kelas berpotensi menyimpan metadata individual untuk semua properti yang diwarisi dari kelas dasar, berdasarkan per jenis.

Contoh berikut mengambil alih metadata untuk properti dependensi DefaultStyleKey. Mengambil alih metadata untuk properti dependensi khusus ini adalah bagian dari pola implementasi untuk membuat kontrol yang dapat menggunakan gaya default dari tema.

public class SpinnerControl : ItemsControl
{
    static SpinnerControl() => DefaultStyleKeyProperty.OverrideMetadata(
            typeof(SpinnerControl),
            new FrameworkPropertyMetadata(typeof(SpinnerControl))
        );
}
Public Class SpinnerControl
    Inherits ItemsControl
    Shared Sub New()
        DefaultStyleKeyProperty.OverrideMetadata(GetType(SpinnerControl), New FrameworkPropertyMetadata(GetType(SpinnerControl)))
    End Sub
End Class

Untuk informasi selengkapnya tentang mengganti atau mengakses metadata untuk properti dependensi, lihat Mengambil alih metadata untuk properti dependensi.

Pewarisan nilai properti

Elemen dapat mewarisi nilai properti dependensi dari induknya di pohon objek.

Nota

Perilaku pewarisan nilai properti tidak diaktifkan secara global untuk semua properti dependensi, karena waktu perhitungan untuk pewarisan memengaruhi performa. Pewarisan nilai properti biasanya hanya diaktifkan dalam skenario yang menyarankan penerapan. Anda dapat memeriksa apakah properti dependensi mewarisi dengan melihat bagian Informasi Properti Dependensi untuk properti dependensi tersebut dalam referensi SDK.

Contoh berikut menunjukkan pengikatan yang menyertakan properti DataContext untuk menentukan sumber pengikatan. Jadi, dalam objek anak, pengikatan tidak perlu menentukan sumber dan dapat menggunakan nilai yang diwariskan dari DataContext di dalam objek induk StackPanel. Atau, objek anak dapat langsung menentukan DataContext sendiri atau Source di Binding, dan tidak menggunakan nilai yang diwariskan.

<StackPanel Canvas.Top="50" DataContext="{Binding Source={StaticResource TestData}}">
    <Button Content="{Binding XPath=test[2]/@text}"/>
</StackPanel>

Untuk informasi selengkapnya, lihat Pewarisan nilai properti.

Integrasi perancang WPF

Kontrol kustom dengan properti yang diimplementasikan sebagai properti dependensi terintegrasi dengan baik dengan WPF Designer untuk Visual Studio. Salah satu contohnya adalah kemampuan untuk mengedit properti dependensi langsung dan terlampir di jendela Properti. Untuk informasi selengkapnya, lihat Gambaran umum penulisan kontrol

Prioritas nilai properti dependensi

Salah satu input berbasis properti dalam sistem properti WPF dapat mengatur nilai properti dependensi. Prinsip prioritas nilai properti Dependensi ada sehingga berbagai skenario tentang bagaimana properti mendapatkan nilainya berinteraksi dengan cara yang dapat diprediksi.

Nota

Dokumentasi SDK terkadang menggunakan istilah "nilai lokal" atau "nilai yang ditetapkan secara lokal" saat membahas properti dependensi. Nilai yang ditetapkan secara lokal adalah nilai properti yang diatur langsung pada instans objek dalam kode, atau sebagai atribut elemen di XAML.

Contoh berikutnya menyertakan gaya yang berlaku untuk properti Background tombol apa pun, tetapi menentukan satu tombol dengan properti Background yang diatur secara lokal. Secara teknis, tombol tersebut memiliki properti Background yang ditetapkan dua kali, meskipun hanya satu nilai yang berlaku—nilai dengan prioritas tertinggi. Nilai yang ditetapkan secara lokal memiliki prioritas tertinggi, kecuali untuk animasi yang sedang berjalan, yang tidak ada di sini. Jadi, tombol kedua menggunakan nilai yang ditetapkan secara lokal untuk properti Background, bukan nilai setter gaya. Tombol pertama tidak memiliki nilai lokal, atau nilai lain yang memiliki prioritas lebih tinggi dibandingkan setter gaya, sehingga menggunakan nilai dari setter gaya untuk properti Background.

<StackPanel>
    <StackPanel.Resources>
        <Style x:Key="{x:Type Button}" TargetType="{x:Type Button}">
            <Setter Property="Background" Value="Orange"/>
        </Style>
    </StackPanel.Resources>
    <Button>I am styled orange</Button>
    <Button Background="Pink">I am locally set to pink (not styled orange)</Button>
</StackPanel>

Mengapa ada prioritas untuk properti dependensi?

Nilai yang ditetapkan secara lokal lebih diutamakan daripada nilai setter gaya, yang mendukung kontrol lokal properti elemen. Untuk detailnya, lihat urutan nilai properti dependensi .

Nota

Sejumlah properti yang ditentukan pada elemen WPF bukan properti dependensi, karena properti dependensi biasanya hanya diterapkan ketika fitur sistem properti WPF diperlukan. Fitur-fiturnya termasuk pengikatan data, gaya, animasi, dukungan nilai default, warisan, properti terlampir, dan pembatalan.

Mempelajari selengkapnya tentang properti dependensi

  • Pengembang komponen atau pengembang aplikasi mungkin ingin membuat properti dependensi mereka sendiri untuk menambahkan kemampuan, seperti dukungan pengikatan data atau gaya, serta dukungan pembatalan validitas dan penyesuaian nilai. Untuk informasi lebih lanjut, lihat Properti dependensi kustom.

  • Pertimbangkan properti dependensi sebagai properti publik, yang dapat diakses atau diketahui oleh pihak mana pun yang memiliki akses ke instans. Untuk informasi selengkapnya, lihat keamanan properti dependensi.

  • Properti terlampir adalah jenis properti yang mendukung sintaksis khusus dalam XAML. Properti terlampir sering tidak memiliki korespondensi 1:1 dengan properti runtime bahasa umum dan belum tentu merupakan properti dependensi. Tujuan utama properti terlampir adalah untuk memungkinkan elemen anak melaporkan nilai properti ke elemen induk, bahkan jika elemen induk dan elemen turunan tidak menyertakan properti tersebut sebagai bagian dari daftar anggota kelas. Salah satu skenario utama adalah mengaktifkan elemen turunan untuk memberi tahu elemen induk cara menyajikannya di UI. Misalnya, lihat Dock dan Left. Untuk informasi selengkapnya, lihat gambaran umum properti terlampir .

Lihat juga