Bagikan melalui


Prioritas nilai properti dependensi

Pekerjaan sistem properti Windows Presentation Foundation (WPF) memengaruhi nilai properti dependensi. Artikel ini menjelaskan bagaimana prioritas input berbasis properti yang berbeda dalam sistem properti WPF menentukan nilai efektif properti dependensi.

Prasyarat

Artikel ini mengasumsikan pengetahuan dasar tentang properti dependensi, dan 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.

Sistem properti WPF

Sistem properti WPF menggunakan berbagai faktor untuk menentukan nilai properti dependensi, seperti validasi properti waktu nyata, pengikatan waktu tunda, dan pemberitahuan perubahan pada properti terkait. Meskipun urutan dan logika yang digunakan untuk menentukan nilai properti dependensi kompleks, mempelajarinya dapat membantu Anda menghindari pengaturan properti yang tidak perlu, dan juga untuk mencari tahu mengapa upaya untuk menetapkan properti dependensi tidak menghasilkan nilai yang diharapkan.

Properti dependensi diatur di beberapa tempat

Contoh XAML berikut menunjukkan bagaimana tiga operasi "set" yang berbeda pada properti Background tombol dapat memengaruhi nilainya.

<StackPanel>
    <StackPanel.Resources>
        <ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type Button}">
            <Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" 
                    BorderBrush="{TemplateBinding BorderBrush}">
                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
            </Border>
        </ControlTemplate>
    </StackPanel.Resources>

    <Button Template="{StaticResource ButtonTemplate}" Background="Red">
        <Button.Style>
            <Style TargetType="{x:Type Button}">
                <Setter Property="Background" Value="Blue"/>
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="Yellow" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
        Which color do you expect?
    </Button>
</StackPanel>

Dalam contoh ini, properti Background disetel secara lokal ke Red. Namun, gaya implisit yang dideklarasikan dalam cakupan tombol, mencoba mengatur properti Background ke Blue. Dan, ketika mouse berada di atas tombol, pemicu dalam gaya implisit mencoba mengatur properti Background ke Yellow. Kecuali untuk paksaan dan animasi, nilai properti yang ditetapkan secara lokal memiliki prioritas tertinggi, sehingga tombol akan berwarna merah—bahkan pada mouseover. Tetapi, jika Anda menghapus nilai yang ditetapkan secara lokal dari tombol, maka tombol tersebut akan mengambil nilai warna Background dari gaya. Dalam gaya, pemicu memiliki prioritas, karena tombol akan berubah menjadi kuning saat penunjuk mouse berada di atasnya, dan biru di keadaan lainnya. Contoh menggantikan nilai default ControlTemplate pada tombol karena templat default memiliki nilai mouseover Background yang tertulis tetap.

Daftar urutan prioritas untuk properti dependensi

Daftar berikut adalah urutan prioritas definitif yang digunakan sistem properti saat menetapkan nilai runtime ke properti dependensi. Prioritas tertinggi tercantum terlebih dahulu.

  1. koersi sistem properti. Untuk informasi selengkapnya tentang paksaan, lihat Paksaan dan animasi.

  2. Animasi aktif, atau animasi dengan perilaku Menahan. Untuk memiliki efek praktis, nilai animasi harus lebih diutamakan daripada nilai dasar (tidak dianimasikan), bahkan jika nilai dasar diatur secara lokal. Untuk informasi selengkapnya, lihat Pemaksaan dan Animasi.

  3. Nilai-nilai lokal. Anda dapat mengatur nilai lokal melalui properti "wrapper", yang sama dengan mengatur atribut atau elemen properti di XAML, atau dengan panggilan ke API SetValue menggunakan properti instans tertentu. Nilai lokal yang ditetapkan melalui pengikatan atau sumber daya akan memiliki prioritas yang sama dengan nilai yang diatur langsung.

  4. nilai-nilai properti templat dari TemplatedParent. Elemen memiliki TemplatedParent jika dibuat oleh templat (ControlTemplate atau DataTemplate). Untuk informasi selengkapnya, lihat TemplatedParent. Dalam templat yang ditentukan oleh TemplatedParent, urutan prioritasnya adalah:

    1. Pemicu.

    2. Kumpulan properti, biasanya melalui atribut XAML.

  5. Gaya implisit. Hanya berlaku untuk properti Style. Nilai Style adalah sumber daya gaya apa pun dengan nilai TargetType yang cocok dengan jenis elemen. Sumber daya gaya harus ada di dalam halaman atau aplikasi. Pencarian sumber daya gaya implisit tidak mencakup sumber daya gaya dalam tema-tema.

  6. Gaya memicu. Pemicu gaya adalah pemicu yang ada dalam gaya eksplisit atau implisit. Gaya harus ada di dalam halaman atau aplikasi. Pemicu dalam gaya default memiliki prioritas yang lebih rendah.

  7. Pemicu Template . Pemicu templat adalah pemicu dari templat yang diterapkan langsung, atau dari templat yang ada dalam suatu gaya. Gaya harus ada di dalam halaman atau aplikasi.

  8. Nilai pengaturan gaya. Nilai setter gaya adalah nilai yang diterapkan oleh Setter dalam gaya. Gaya harus ada di dalam halaman atau aplikasi.

  9. Gaya default, juga dikenal sebagai gaya tema . Untuk informasi selengkapnya, lihat gaya Default (Tema) . Dalam gaya default, urutan prioritasnya adalah:

    1. Pemicu aktif.

    2. Setter.

  10. Warisan. Beberapa properti dependensi elemen anak mewarisi nilainya dari elemen induk. Jadi, mungkin tidak perlu mengatur nilai properti pada setiap elemen di seluruh aplikasi. Untuk informasi selengkapnya, lihat Pewarisan nilai properti.

  11. Nilai default dari metadata properti dependensi Properti dependensi dapat memiliki nilai default yang ditetapkan selama pendaftaran sistem properti properti tersebut. Kelas turunan yang mewarisi properti dependensi dapat mengambil alih metadata properti dependensi (termasuk nilai default) per jenis. Untuk informasi selengkapnya, lihat metadata properti ketergantungan . Untuk properti yang diwariskan, nilai default elemen induk lebih diutamakan daripada nilai default elemen turunan. Jadi, jika properti yang dapat diwariskan tidak diatur, nilai default akar atau induk digunakan alih-alih nilai default elemen turunan.

TemplatedParent

TemplatedParent prioritas tidak berlaku untuk properti elemen yang dideklarasikan langsung dalam markup aplikasi standar. Konsep TemplatedParent hanya ada untuk item anak dalam pohon visual yang muncul melalui aplikasi templat. Saat sistem properti mencari templat yang ditentukan oleh TemplatedParent untuk nilai properti elemen, sistem properti mencari templat yang membuat elemen. Nilai properti dari templat TemplatedParent umumnya bertindak seolah-olah nilai ditetapkan secara lokal pada elemen, tetapi dengan prioritas yang lebih rendah daripada nilai lokal aktual karena templat berpotensi dibagikan. Untuk informasi selengkapnya, lihat TemplatedParent .

Properti Gaya

Urutan prioritas yang sama berlaku untuk semua properti dependensi, kecuali properti Style. Properti Style unik karena tidak dapat ditata dengan sendirinya. Memaksakan atau menganimasikan properti Style tidak disarankan (dan menganimasikan properti Style akan memerlukan kelas animasi kustom). Akibatnya, tidak semua item prioritas berlaku. Hanya ada tiga cara untuk mengatur properti Style:

  • Gaya eksplisit. Properti Style elemen diberikan secara langsung. Nilai properti Style bertindak seolah-olah itu adalah nilai lokal dan memiliki prioritas yang sama dengan item 3 dalam daftar prioritas . Dalam sebagian besar skenario, gaya eksplisit tidak didefinisikan sebaris dan sebaliknya secara eksplisit direferensikan sebagai sumber daya, misalnya Style="{StaticResource myResourceKey}".

  • Gaya implisit. Properti Style elemen tidak disetel secara langsung. Sebaliknya, gaya diterapkan ketika terdapat pada beberapa tingkat dalam halaman atau aplikasi, dan memiliki kunci sumber daya yang sesuai dengan jenis elemen pada mana gaya diterapkan, misalnya <Style TargetType="x:Type Button">. Jenisnya harus sama persis, misalnya <Style TargetType="x:Type Button"> tidak akan diterapkan ke jenis MyButton bahkan jika MyButton berasal dari Button. Nilai properti Style memiliki prioritas yang sama dengan item 5 dalam daftar prioritas . Nilai gaya implisit dapat dideteksi dengan memanggil metode DependencyPropertyHelper.GetValueSource, meneruskan properti Style, dan memeriksa ImplicitStyleReference dalam hasil.

  • Gaya default, juga dikenal sebagai gaya tema . Properti Style elemen tidak disetel secara langsung. Sebaliknya, itu berasal dari evaluasi tema runtime oleh mesin presentasi WPF. Sebelum runtime, nilai properti Style adalah null. Nilai properti Style memiliki prioritas yang sama dengan item 9 dalam daftar prioritas .

Gaya default (Tema)

Setiap kontrol yang dikirim dengan WPF memiliki gaya default yang dapat bervariasi menurut tema, itulah sebabnya gaya default kadang-kadang disebut sebagai gaya tema .

ControlTemplate adalah item penting dalam gaya default untuk kontrol. ControlTemplate adalah nilai setter untuk properti Template gaya. Jika gaya default tidak berisi templat, kontrol tanpa templat kustom sebagai bagian dari gaya kustom tidak akan memiliki tampilan visual. Templat tidak hanya menentukan tampilan visual kontrol, templat juga menentukan koneksi antara properti di pohon visual templat dan kelas kontrol yang sesuai. Setiap kontrol mengekspos sekumpulan properti yang dapat memengaruhi tampilan visual kontrol tanpa mengganti templat. Misalnya, pertimbangkan tampilan visual default kontrol Thumb, yang merupakan komponen ScrollBar.

Kontrol Thumb memiliki properti tertentu yang dapat disesuaikan. Templat default kontrol Thumb membuat struktur dasar, atau pohon visual, dengan beberapa komponen Border berlapis untuk membuat tampilan berlekuk. Dalam templat, properti yang dimaksudkan untuk dapat disesuaikan oleh kelas Thumb diekspos melalui TemplateBinding

Gaya default menentukan TargetType dalam definisinya. Evaluasi tema runtime mencocokkan TargetType dari gaya default dengan properti DefaultStyleKey dari kontrol. Sebaliknya, perilaku pencarian untuk gaya implisit menggunakan jenis kontrol yang sebenarnya. Nilai DefaultStyleKey diwariskan oleh kelas turunan, sehingga elemen turunan yang mungkin tidak memiliki gaya terkait mendapatkan tampilan visual default. Misalnya, jika Anda memperoleh MyButton dari Button, MyButton akan mewarisi templat default Button. Kelas turunan dapat mengambil alih nilai default DefaultStyleKey dalam metadata properti dependensi. Jadi, jika Anda menginginkan representasi visual yang berbeda untuk MyButton, Anda dapat mengambil alih metadata properti dependensi untuk DefaultStyleKey pada MyButton, lalu menentukan gaya default yang relevan termasuk templat, yang akan Anda kemas dengan kontrol MyButton Anda. Untuk informasi selengkapnya, lihat Gambaran umum penulisan kontrol

Sumber daya dinamis

Sumber daya dinamis

Referensi sumber daya dinamis bukan bagian teknis dari sistem properti, dan memiliki urutan pencarian mereka sendiri yang berinteraksi dengan daftar prioritas . Pada dasarnya, prioritas referensi sumber daya dinamis adalah: elemen ke akar halaman, aplikasi, tema, dan kemudian sistem. Untuk informasi selengkapnya, lihat Sumber Daya XAML.

Meskipun referensi dan pengikatan sumber daya dinamis memiliki prioritas terhadap lokasi tempat mereka ditetapkan, nilainya ditunda. Salah satu konsekuensi dari ini adalah bahwa jika Anda mengatur sumber daya dinamis atau mengikat ke nilai lokal, setiap perubahan pada nilai lokal sepenuhnya menggantikan sumber daya atau pengikatan dinamis. Bahkan jika Anda memanggil metode ClearValue untuk menghapus nilai yang ditetapkan secara lokal, sumber daya atau pengikatan dinamis tidak akan dipulihkan. Bahkan, jika Anda memanggil ClearValue pada properti yang memiliki sumber daya atau pengikatan dinamis (tanpa nilai lokal harfiah), sumber daya dinamis atau pengikatan akan dihapus.

TetapkanNilaiSaatIni

Metode SetCurrentValue adalah cara lain untuk mengatur properti, tetapi tidak ada dalam daftar prioritas . SetCurrentValue memungkinkan Anda mengubah nilai properti tanpa menimpa sumber nilai sebelumnya. Misalnya, jika properti diatur oleh pemicu, lalu Anda menetapkan nilai lain menggunakan SetCurrentValue, tindakan pemicu berikutnya akan mengatur kembali properti ke nilai pemicu. Anda dapat menggunakan SetCurrentValue kapan pun Anda ingin menetapkan nilai properti tanpa memberikan nilai tersebut tingkat prioritas nilai lokal. Demikian pula, Anda dapat menggunakan SetCurrentValue untuk mengubah nilai properti tanpa menimpa pengikatan.

Paksaan dan animasi

Koersi dan animasi keduanya mempengaruhi nilai dasar . Nilai dasar adalah nilai properti dependensi dengan prioritas tertinggi, ditentukan dengan mengevaluasi ke atas melalui daftar prioritas hingga item 2 tercapai.

Jika animasi tidak menentukan nilai properti From dan To untuk perilaku tertentu, atau jika animasi sengaja kembali ke nilai dasar saat selesai, maka nilai dasar dapat memengaruhi nilai animasi. Untuk melihat ini dalam praktiknya, jalankan aplikasi sampel Nilai Target. Dalam sampel, untuk tinggi persegi panjang, coba atur nilai lokal awal yang berbeda dari nilai From apa pun. Animasi sampel segera dimulai dengan menggunakan nilai From alih-alih nilai dasar. Dengan menentukan Stop sebagai FillBehavior, setelah menyelesaikan animasi akan mengatur ulang nilai properti ke nilai dasarnya. Prioritas normal digunakan untuk penentuan nilai dasar setelah animasi berakhir.

Beberapa animasi dapat diterapkan ke satu properti, dengan setiap animasi memiliki prioritas yang berbeda. Daripada menerapkan animasi dengan prioritas tertinggi, mesin presentasi WPF mungkin menggabungkan nilai animasi, tergantung pada bagaimana animasi ditentukan dan jenis nilai yang dianimasikan. Untuk informasi selengkapnya, lihat Gambaran umum animasi

Pemaksaan berada di bagian atas daftar prioritas . Bahkan animasi yang sedang berjalan tunduk pada koersi nilai. Beberapa properti dependensi yang ada di WPF memiliki koersi bawaan. Untuk properti dependensi kustom, Anda dapat menentukan perilaku koersi dengan menulis CoerceValueCallback yang Anda berikan sebagai bagian dari metadata saat membuat properti. Anda juga dapat mengambil alih perilaku koersi properti yang ada dengan mengambil alih metadata untuk properti tersebut di kelas turunan. Paksaan berinteraksi dengan nilai dasar sedemikian rupa sehingga batasan pada paksaan diterapkan sesuai dengan kondisi saat itu, tetapi nilai dasar tetap dipertahankan. Akibatnya, jika batasan dalam paksaan kemudian dicabut, paksaan akan mengembalikan nilai terdekat yang mungkin dengan nilai dasar, dan berpotensi pengaruh paksaan pada properti akan berhenti segera setelah semua batasan diangkat. Untuk informasi lebih lanjut mengenai perilaku pemaksaan, lihat fungsi panggilan balik properti dependensi dan validasi.

Perilaku pemicu

Kontrol sering mendefinisikan perilaku pemicu sebagai bagian dari gaya default . Mengatur properti lokal pada kontrol dapat berpotensi bertentangan dengan pemicu tersebut, mencegah pemicu merespons (baik secara visual atau perilaku) ke peristiwa yang digerakkan pengguna. Penggunaan umum pemicu properti adalah untuk mengontrol properti status, seperti IsSelected atau IsEnabled. Misalnya, secara default, saat Button dinonaktifkan, penerapan gaya tema (IsEnabled adalah false) mengatur nilai Foreground untuk membuat Button tampak abu-abu. Jika Anda telah menetapkan nilai Foreground lokal, nilai properti lokal dengan prioritas lebih tinggi akan menggantikan nilai gaya tema Foreground, bahkan jika Button dinonaktifkan. Saat mengatur nilai properti yang mengambil alih perilaku pemicu tingkat tema untuk kontrol, berhati-hatilah untuk tidak mengganggu pengalaman pengguna yang dimaksudkan untuk kontrol tersebut.

ClearValue

Metode ClearValue menghapus nilai properti dependensi yang diterapkan secara lokal untuk elemen. Tetapi, memanggil ClearValue tidak menjamin bahwa nilai default yang ditetapkan dalam metadata selama pendaftaran properti adalah nilai efektif baru. Semua peserta lain dalam daftar prioritas masih aktif, dan hanya nilai yang ditetapkan secara lokal yang dihapus. Misalnya, jika Anda memanggil ClearValue pada properti yang memiliki gaya tema, nilai gaya tema akan diterapkan sebagai nilai baru, bukan default berbasis metadata. Jika Anda ingin mengatur nilai properti ke nilai default metadata terdaftar, dapatkan nilai metadata default dengan mengkueri metadata properti dependensi, dan atur nilai properti secara lokal dengan panggilan ke SetValue.

Lihat juga