Bagikan melalui


Gambaran umum properti dependensi

Windows Presentation Foundation (WPF) menyediakan serangkaian layanan yang dapat digunakan untuk memperluas fungsionalitas properti jenis. Secara kolektif, layanan ini biasanya 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. Ini 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

Topik ini mengasumsikan bahwa Anda memiliki beberapa pengetahuan dasar tentang sistem jenis .NET dan pemrograman berorientasi objek. Untuk mengikuti contoh dalam topik ini, Anda juga harus memahami XAML dan tahu cara menulis aplikasi WPF. Untuk informasi selengkapnya, lihat Panduan: Aplikasi desktop WPF pertama saya.

Properti dependensi dan properti CLR

Di WPF, properti biasanya diekspos sebagai properti .NET standar. Pada tingkat dasar, Anda dapat berinteraksi dengan properti ini secara langsung dan tidak pernah tahu bahwa properti tersebut diimplementasikan sebagai properti dependensi. Namun, Anda harus terbiasa dengan beberapa atau semua fitur sistem properti WPF, sehingga Anda dapat memanfaatkan fitur-fitur ini.

Tujuan properti dependensi adalah untuk memberikan cara untuk menghitung nilai properti berdasarkan nilai input lain. Input lain ini mungkin mencakup properti sistem seperti tema dan preferensi pengguna, mekanisme penentuan properti just-in-time seperti pengikatan data dan animasi/papan cerita, templat multi-penggunaan seperti sumber daya dan gaya, atau nilai yang dikenal melalui hubungan induk-anak dengan elemen lain di pohon elemen. Selain itu, properti dependensi dapat diimplementasikan untuk menyediakan validasi mandiri, nilai default, panggilan balik yang memantau perubahan pada properti lain, dan sistem yang dapat memaksa nilai properti berdasarkan informasi runtime yang berpotensi. Kelas turunan juga dapat mengubah beberapa karakteristik spesifik properti yang ada dengan mengambil alih metadata properti dependensi, daripada mengesampingkan implementasi aktual dari properti yang ada atau membuat properti baru.

Dalam referensi SDK, Anda dapat mengidentifikasi properti mana yang merupakan properti dependensi dengan adanya bagian Informasi Properti Dependensi pada halaman referensi terkelola untuk properti tersebut. Bagian Informasi Properti Dependensi menyertakan tautan ke bidang pengidentifikasi untuk properti dependensi tersebut DependencyProperty , dan juga menyertakan daftar opsi metadata yang diatur untuk properti tersebut, informasi penggantian per kelas, dan detail lainnya.

Properti dependensi kembali properti CLR

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

Berikut ini mencantumkan terminologi yang digunakan dengan properti dependensi:

  • Properti dependensi: Properti yang didukung oleh DependencyProperty.

  • Pengidentifikasi properti dependensi:DependencyProperty Instans, yang diperoleh sebagai nilai pengembalian saat mendaftarkan properti dependensi, lalu disimpan sebagai anggota statis kelas. Pengidentifikasi ini digunakan sebagai parameter untuk banyak API yang berinteraksi dengan sistem properti WPF.

  • CLR "wrapper": Implementasi aktual get and set untuk properti. Implementasi ini menggabungkan pengidentifikasi properti dependensi dengan menggunakannya dalam GetValue panggilan dan SetValue , sehingga menyediakan dukungan untuk properti menggunakan sistem properti WPF.

Contoh berikut mendefinisikan IsSpinning properti dependensi, dan menunjukkan hubungan DependencyProperty pengidentifikasi dengan properti yang didukungnya.

public static readonly DependencyProperty IsSpinningProperty =
    DependencyProperty.Register(
    "IsSpinning", typeof(Boolean),
    typeof(MyCode)
    );
public bool IsSpinning
{
    get { return (bool)GetValue(IsSpinningProperty); }
    set { SetValue(IsSpinningProperty, value); }
}
Public Shared ReadOnly IsSpinningProperty As DependencyProperty =
    DependencyProperty.Register("IsSpinning",
                                GetType(Boolean),
                                GetType(MyCode))

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

Konvensi penamaan properti dan bidang dukungannya DependencyProperty penting. Nama bidang selalu nama properti , dengan akhiran Property 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 menentukan warna latar belakang tombol sebagai merah. Contoh ini menggambarkan kasus di mana nilai string sederhana untuk atribut XAML dikonversi jenis oleh pengurai WPF XAML menjadi jenis WPF ( Color, dengan cara SolidColorBrush) dalam kode yang dihasilkan.

<Button Background="Red" Content="Button!"/>

XAML mendukung berbagai bentuk sintaks untuk mengatur properti. Sintaks mana yang akan digunakan untuk properti tertentu akan bergantung pada jenis nilai yang digunakan properti, serta faktor lain seperti keberadaan pengonversi jenis. Untuk informasi selengkapnya tentang sintaks XAML untuk pengaturan properti, lihat XAML dalam Sintaks WPF dan XAML Secara Terperinci.

Sebagai contoh sintaks non-atribut, contoh XAML berikut menunjukkan latar belakang tombol lain. Kali ini daripada mengatur warna solid sederhana, latar belakang diatur ke gambar, dengan elemen yang mewakili gambar tersebut dan sumber gambar tersebut ditentukan sebagai atribut elemen berlapis. Ini adalah contoh sintaks elemen properti.

<Button Content="Button!">
  <Button.Background>
    <ImageBrush ImageSource="wavy.jpg"/>
  </Button.Background>
</Button>

Mengatur properti dalam kode

Mengatur nilai properti dependensi dalam kode biasanya hanya panggilan ke implementasi yang ditetapkan yang diekspos oleh "pembungkus" CLR.

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

Mendapatkan nilai properti juga pada dasarnya adalah panggilan ke implementasi "wrapper":

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

Anda juga dapat memanggil API GetValue sistem properti dan SetValue secara langsung. Ini biasanya tidak diperlukan jika Anda menggunakan properti yang ada (pembungkus lebih nyaman, dan memberikan paparan properti yang lebih baik untuk alat pengembang), tetapi memanggil API secara langsung sesuai untuk skenario tertentu.

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

Fungsionalitas properti yang disediakan oleh properti dependensi

Properti dependensi menyediakan fungsionalitas yang memperluas fungsionalitas properti dibandingkan dengan properti yang didukung oleh bidang. Seringkali, fungsionalitas tersebut mewakili atau mendukung salah satu fitur spesifik berikut:

Sumber

Nilai properti dependensi dapat diatur dengan mereferensikan sumber daya. Sumber daya biasanya ditentukan sebagai Resources nilai properti dari elemen akar halaman, atau aplikasi (lokasi ini memungkinkan akses paling nyaman ke sumber daya). Contoh berikut menunjukkan cara menentukan SolidColorBrush sumber daya.

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

Setelah sumber daya ditentukan, Anda dapat mereferensikan sumber daya dan menggunakannya untuk memberikan nilai properti:

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

Sumber daya khusus ini direferensikan sebagai DynamicResource Markup Extension (dalam WPF XAML, Anda dapat menggunakan referensi sumber daya statis atau dinamis). Untuk menggunakan referensi sumber daya dinamis, Anda harus mengatur ke properti dependensi, sehingga khususnya penggunaan referensi sumber daya dinamis yang diaktifkan oleh sistem properti WPF. Untuk informasi selengkapnya, lihat Sumber Daya XAML.

Catatan

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 Prioritas Nilai Properti Dependensi.

Pengikatan data

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

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

<Button Content="{Binding XPath=Team/@TeamName}"/>

Catatan

Pengikatan diperlakukan sebagai nilai lokal, yang berarti bahwa jika Anda menetapkan nilai lokal lain, Anda akan menghilangkan pengikatan. Untuk detailnya, lihat Prioritas Nilai Properti Dependensi.

Properti dependensi, atau DependencyObject kelas , tidak secara asli mendukung INotifyPropertyChanged untuk tujuan menghasilkan pemberitahuan perubahan DependencyObject nilai properti sumber 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 dua skenario utama yang memotivasi untuk menggunakan properti dependensi. Gaya sangat berguna untuk mengatur properti yang menentukan antarmuka pengguna aplikasi (UI). Gaya biasanya didefinisikan sebagai sumber daya di XAML. Gaya berinteraksi dengan sistem properti karena biasanya berisi "setter" untuk properti tertentu, serta "pemicu" yang mengubah nilai properti berdasarkan nilai real-time untuk properti lain.

Contoh berikut membuat gaya sederhana (yang akan didefinisikan di dalam Resources kamus, tidak ditampilkan), lalu menerapkan gaya tersebut langsung ke Style properti untuk Button. Setter dalam gaya mengatur Background properti untuk ditata Button ke hijau.

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

Untuk informasi selengkapnya, lihat Gaya dan Templat.

Animasi

Properti dependensi dapat dianimasikan. Saat animasi diterapkan dan berjalan, nilai animasi beroperasi dengan prioritas yang lebih tinggi daripada nilai apa pun (seperti nilai lokal) yang dimiliki properti.

Contoh berikut menganimasikan Background pada Button properti (secara teknis, Background dianimasikan dengan menggunakan sintaks elemen properti untuk menentukan kosong SolidColorBrush sebagai Background, maka Color properti tersebut SolidColorBrush adalah properti yang secara langsung dianimasikan).

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

Untuk informasi selengkapnya tentang menganimasikan properti, lihat Gambaran Umum Animasi dan Ringkasan Papan Cerita.

Penimpaan metadata

Anda dapat mengubah perilaku tertentu dari properti dependensi dengan mengambil alih metadata untuk properti tersebut ketika Anda berasal dari kelas yang awalnya mendaftarkan properti dependensi. Mengambil alih metadata bergantung pada DependencyProperty pengidentifikasi. Mengambil alih metadata tidak memerlukan pengisian 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 DefaultStyleKeydependensi . Mengambil alih metadata properti dependensi khusus ini adalah bagian dari pola implementasi yang 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 mengambil alih atau mendapatkan metadata properti, lihat Metadata Properti Dependensi.

Warisan nilai properti

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

Catatan

Perilaku pewarisan nilai properti tidak diaktifkan secara global untuk semua properti dependensi, karena waktu perhitungan untuk pewarisan memang memiliki beberapa dampak performa. Pewarisan nilai properti biasanya hanya diaktifkan untuk properti di mana skenario tertentu menunjukkan bahwa pewarisan nilai properti sesuai. Anda dapat menentukan apakah properti dependensi mewarisi dengan melihat bagian Informasi Properti Dependensi untuk properti dependensi tersebut dalam referensi SDK.

Contoh berikut menunjukkan pengikatan, dan mengatur DataContext properti yang menentukan sumber pengikatan, yang tidak ditampilkan dalam contoh pengikatan sebelumnya. Setiap pengikatan berikutnya dalam objek anak tidak perlu menentukan sumbernya, mereka dapat menggunakan nilai yang diwariskan dari DataContext dalam objek induk StackPanel . (Atau, objek anak dapat memilih untuk secara langsung menentukan sendiri DataContext atau di SourceBinding, dan untuk sengaja tidak menggunakan nilai yang diwariskan untuk konteks data pengikatannya.)

<StackPanel Canvas.Top="50" DataContext="{Binding Source={StaticResource XmlTeamsSource}}">
  <Button Content="{Binding XPath=Team/@TeamName}"/>
</StackPanel>

Untuk informasi selengkapnya, lihat Pewarisan Nilai Properti.

Integrasi perancang WPF

Kontrol kustom dengan properti yang diimplementasikan sebagai properti dependensi akan menerima dukungan WPF Designer untuk Visual Studio yang sesuai. Salah satu contohnya adalah kemampuan untuk mengedit properti dependensi langsung dan terlampir dengan jendela Properti . Untuk informasi selengkapnya, lihat Gambaran Umum Penulisan Kontrol.

Nilai properti dependensi didahulukan

Ketika Anda mendapatkan nilai properti dependensi, Anda berpotensi mendapatkan nilai yang ditetapkan pada properti tersebut melalui salah satu input berbasis properti lainnya yang berpartisipasi dalam sistem properti WPF. Prioritas nilai properti dependensi ada sehingga berbagai skenario tentang bagaimana properti mendapatkan nilainya dapat berinteraksi dengan cara yang dapat diprediksi.

Pertimbangkan contoh berikut. Contohnya mencakup gaya yang berlaku untuk semua tombol dan propertinya Background , tetapi kemudian juga menentukan satu tombol dengan nilai yang ditetapkan Background secara lokal.

Catatan

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

Pada prinsipnya, untuk tombol pertama, properti diatur dua kali, tetapi hanya satu nilai yang berlaku: nilai dengan prioritas tertinggi. Nilai yang ditetapkan secara lokal memiliki prioritas tertinggi (kecuali untuk animasi yang sedang berjalan, tetapi tidak ada animasi yang berlaku dalam contoh ini) dan dengan demikian nilai yang ditetapkan secara lokal digunakan alih-alih nilai setter gaya untuk latar belakang pada tombol pertama. Tombol kedua tidak memiliki nilai lokal (dan tidak ada nilai lain dengan prioritas yang lebih tinggi daripada setter gaya) dan dengan demikian latar belakang di tombol tersebut berasal dari setter gaya.

<StackPanel>
  <StackPanel.Resources>
    <Style x:Key="{x:Type Button}" TargetType="{x:Type Button}">
     <Setter Property="Background" Value="Red"/>
    </Style>
  </StackPanel.Resources>
  <Button Background="Green">I am NOT red!</Button>
  <Button>I am styled red</Button>
</StackPanel>

Mengapa properti dependensi diutamakan ada?

Biasanya, Anda tidak ingin gaya selalu diterapkan dan mengaburkan bahkan nilai elemen individual yang ditetapkan secara lokal (jika tidak, akan sulit untuk menggunakan gaya atau elemen secara umum). Oleh karena itu, nilai yang berasal dari gaya beroperasi pada preseden yang lebih rendah daripada nilai yang ditetapkan secara lokal. Untuk daftar properti dependensi yang lebih menyeluruh dan asal nilai efektif properti dependensi, lihat Prioritas Nilai Properti Dependensi.

Catatan

Ada sejumlah properti yang ditentukan pada elemen WPF yang bukan properti dependensi. Menurut dan besar, properti diimplementasikan sebagai properti dependensi hanya ketika ada kebutuhan untuk mendukung setidaknya salah satu skenario yang diaktifkan oleh sistem properti: pengikatan data, gaya, animasi, dukungan nilai default, warisan, properti terlampir, atau pembatalan.

Pembelajaran selengkapnya tentang 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 (CLR), dan belum tentu merupakan properti dependensi. Tujuan umum properti terlampir adalah untuk memungkinkan elemen anak melaporkan nilai properti ke elemen induk, bahkan jika elemen induk dan elemen turunan tidak memiliki properti tersebut sebagai bagian dari daftar anggota kelas. Salah satu skenario utama adalah mengaktifkan elemen turunan untuk memberi tahu induk bagaimana elemen tersebut harus disajikan di UI; misalnya, lihat Dock atau Left. Untuk detailnya, lihat Gambaran Umum Properti Terlampir.

  • Pengembang komponen atau pengembang aplikasi mungkin ingin membuat properti dependensi mereka sendiri, untuk mengaktifkan kemampuan seperti pengikatan data atau dukungan gaya, atau untuk dukungan koersi pembatalan dan nilai. Untuk detailnya, lihat Properti Dependensi Kustom.

  • Pertimbangkan properti dependensi untuk menjadi properti publik, dapat diakses atau setidaknya dapat ditemukan oleh pemanggil apa pun yang memiliki akses ke instans. Untuk informasi selengkapnya, lihat Keamanan Properti Dependensi.

Baca juga