Bagikan melalui


Struktur di WPF

Dalam banyak teknologi, elemen dan komponen diatur dalam struktur pohon di mana pengembang secara langsung memanipulasi simpul objek di pohon untuk memengaruhi penyajian atau perilaku aplikasi. Windows Presentation Foundation (WPF) juga menggunakan beberapa metafora struktur pohon untuk menentukan hubungan antar elemen program. Untuk sebagian besar pengembang WPF dapat membuat aplikasi dalam kode atau menentukan bagian aplikasi di XAML sambil berpikir secara konseptual tentang metafora pohon objek, tetapi akan memanggil API tertentu atau menggunakan markup tertentu untuk melakukannya daripada beberapa API manipulasi pohon objek umum seperti yang mungkin Anda gunakan di XML DOM. WPF mengekspos dua kelas pembantu yang memberikan tampilan metafora pohon, LogicalTreeHelper dan VisualTreeHelper. Istilah pohon visual dan pohon logis juga digunakan dalam dokumentasi WPF karena pohon yang sama ini berguna untuk memahami perilaku fitur WPF kunci tertentu. Topik ini mendefinisikan apa yang diwakili pohon visual dan pohon logis, membahas bagaimana pohon tersebut berhubungan dengan konsep pohon objek secara keseluruhan, dan memperkenalkan LogicalTreeHelper dan VisualTreeHelper.

Pohon di WPF

Struktur pohon yang paling lengkap di WPF adalah pohon objek. Jika Anda ditentukan halaman aplikasi di XAML lalu memuat XAML, struktur pohon dibuat berdasarkan hubungan bertingkat antar elemen dalam markup. Jika Anda menentukan aplikasi atau sebagian aplikasi dalam kode, struktur pohon dibuat berdasarkan cara Anda menetapkan nilai properti untuk properti yang mengimplementasikan model konten untuk objek tertentu. Di WPF, ada dua cara agar pohon objek lengkap dikonsep dan dapat dilaporkan ke API publiknya: sebagai pohon logis dan sebagai pohon visual. Perbedaan antara pohon logis dan pohon visual tidak selalu penting, tetapi kadang-kadang dapat menyebabkan masalah dengan subsistem WPF tertentu dan memengaruhi pilihan yang Anda buat dalam markup atau kode.

Meskipun Anda tidak selalu memanipulasi pohon logis atau pohon visual secara langsung, memahami konsep bagaimana pohon berinteraksi berguna untuk memahami WPF sebagai teknologi. Memikirkan WPF sebagai metafora pohon dari suatu jenis juga penting untuk memahami bagaimana pewarisan properti dan perutean peristiwa berfungsi di WPF.

Nota

Karena pohon objek lebih merupakan konsep daripada API aktual, cara lain untuk memikirkan konsep adalah sebagai grafik objek. Dalam praktiknya, ada hubungan antara objek pada waktu run di mana metafora pohon tidak lagi berlaku. Namun demikian, terutama dengan UI yang ditentukan XAML, metafora pohon cukup relevan sehingga sebagian besar dokumentasi WPF akan menggunakan istilah pohon objek saat mereferensikan konsep umum ini.

Pohon Logis

Di WPF, Anda menambahkan konten ke elemen UI dengan mengatur properti objek yang mendukung elemen tersebut. Misalnya, Anda menambahkan item ke kontrol ListBox dengan memanipulasi properti Items. Dengan melakukan ini, Anda menempatkan item ke dalam ItemCollection yang merupakan nilai properti Items. Demikian pula, untuk menambahkan objek ke DockPanel, Anda memanipulasi nilai properti Children. Di sini, Anda menambahkan objek ke UIElementCollection. Untuk contoh kode, lihat Cara: Menambahkan Elemen secara Dinamis.

Dalam Extensible Application Markup Language (XAML), saat Anda menempatkan item daftar dalam ListBox atau kontrol atau elemen UI lainnya dalam DockPanel, Anda juga menggunakan properti Items dan Children, baik secara eksplisit maupun implisit, seperti dalam contoh berikut.

<DockPanel
  Name="ParentElement"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  >
  <!--implicit: <DockPanel.Children>-->
  <ListBox DockPanel.Dock="Top">
    <!--implicit: <ListBox.Items>-->
    <ListBoxItem>
      <TextBlock>Dog</TextBlock>
    </ListBoxItem>
    <ListBoxItem>
      <TextBlock>Cat</TextBlock>
    </ListBoxItem>
    <ListBoxItem>
      <TextBlock>Fish</TextBlock>
    </ListBoxItem>
  <!--implicit: </ListBox.Items>-->
  </ListBox>
  <Button Height="20" Width="100" DockPanel.Dock="Top">Buy a Pet</Button>
  <!--implicit: </DockPanel.Children>-->
</DockPanel>

Jika Anda memproses XAML ini sebagai XML di bawah model objek dokumen, dan jika Anda telah menyertakan tag yang dikomentari sebagai implisit (yang akan legal), pohon XML DOM yang dihasilkan akan menyertakan elemen untuk <ListBox.Items> dan item implisit lainnya. Tetapi XAML tidak memproses seperti itu ketika Anda membaca markup dan menulis ke objek, grafik objek yang dihasilkan tidak secara harfiah menyertakan ListBox.Items. Namun, properti ListBox bernama Items yang berisi ItemCollection, dan ItemCollection diinisialisasi tetapi kosong ketika ListBox XAML diproses. Kemudian, setiap elemen objek anak yang ada sebagai konten untuk ListBox ditambahkan ke ItemCollection oleh panggilan pengurai ke ItemCollection.Add. Contoh pemrosesan XAML ini ke dalam pohon objek sejauh ini tampaknya merupakan contoh di mana pohon objek yang dibuat pada dasarnya adalah pohon logis.

Namun, pohon logis bukan keseluruhan graf objek yang ada untuk UI aplikasi Anda saat waktu berjalan, meskipun item sintaksis implisit XAML sudah diperhitungkan. Penyebab utamanya adalah visual dan templat. Misalnya, pertimbangkan Button. Pohon logis melaporkan objek Button dan juga stringnya Content. Namun, ada lebih banyak hal tentang tombol ini di pohon objek run-time. Secara khusus, tombol hanya muncul di layar seperti saat ini karena diterapkannya sebuah templat kontrol Button yang spesifik. Visual yang berasal dari templat yang diterapkan (seperti Border abu-abu gelap di sekitar tombol visual) tidak dilaporkan di pohon logis, bahkan jika Anda melihat pohon logis selama waktu proses (seperti memproses peristiwa input dari antarmuka pengguna yang terlihat dan kemudian membaca pohon logis). Untuk menemukan visual templat, Anda sebaiknya meninjau pohon visual.

Untuk informasi selengkapnya tentang cara sintaks XAML memetakan ke grafik objek yang dibuat, dan sintaks implisit dalam XAML, lihat Sintaks XAML Secara Rinci atau XAML di WPF.

Tujuan Pohon Logis

Pohon logis ada sehingga model konten dapat dengan mudah melakukan iterasi atas kemungkinan objek anak mereka, dan sehingga model konten dapat diperluas dan dikembangkan lebih lanjut. Selain itu, pohon logis menyediakan kerangka kerja untuk pemberitahuan tertentu, seperti ketika semua objek di pohon logis dimuat. Pada dasarnya, pohon logis adalah suatu bentuk perkiraan dari grafik objek pada saat runtime di tingkat framework, yang mengecualikan elemen visual, tetapi memadai untuk banyak operasi kueri terhadap komposisi aplikasi runtime Anda sendiri.

Selain itu, referensi sumber daya statis dan dinamis diselesaikan dengan melihat ke atas melalui pohon logis untuk koleksi Resources pada objek permintaan awal, lalu melanjutkan pohon logis dan memeriksa setiap FrameworkElement (atau FrameworkContentElement) untuk nilai Resources lain yang berisi ResourceDictionary, mungkin berisi kunci tersebut. Pohon logis digunakan untuk pencarian sumber daya ketika pohon logis dan pohon visual ada. Untuk informasi selengkapnya tentang kamus dan pencarian sumber daya, lihat Sumber Daya XAML.

Komposisi Pohon Logis

Pohon logis didefinisikan pada tingkat kerangka kerja WPF, yang berarti bahwa elemen dasar WPF yang paling relevan untuk operasi pohon logis adalah FrameworkElement atau FrameworkContentElement. Namun, seperti yang Anda lihat jika Anda benar-benar menggunakan API LogicalTreeHelper, pohon logis terkadang berisi simpul yang tidak FrameworkElement atau FrameworkContentElement. Misalnya, pohon logis melaporkan nilai Text dari TextBlock, yang merupakan string.

Mengabaikan Pohon Logis

Penulis kontrol tingkat lanjut dapat mengambil alih pohon logis dengan mengesampingkan beberapa API yang menentukan bagaimana objek umum atau model konten menambahkan atau menghapus objek di dalam pohon logis. Untuk contoh cara mengambil alih pohon logis, lihat Mengambil alih Pohon Logis.

Pewarisan Nilai Properti

Warisan nilai properti beroperasi melalui pohon hibrid. Metadata aktual yang berisi properti Inherits yang memungkinkan pewarisan properti adalah kelas FrameworkPropertyMetadata tingkat kerangka kerja WPF. Oleh karena itu, objek induk yang memegang nilai asli dan objek anak yang mewarisi nilai tersebut keduanya harus bernilai FrameworkElement atau FrameworkContentElement, dan keduanya harus menjadi bagian dari suatu pohon logis. Namun, untuk properti WPF yang ada yang mendukung pewarisan properti, pewarisan nilai properti dapat berlanjut melalui objek yang menjadi perantara yang tidak termasuk dalam pohon logis. Terutama ini relevan untuk memiliki elemen templat menggunakan nilai properti yang diwariskan yang ditetapkan baik pada instans yang di-template, atau pada tingkat komposisi tingkat halaman yang masih lebih tinggi dan karenanya lebih tinggi di pohon logis. Agar pewarisan nilai properti berfungsi secara konsisten di seluruh batas seperti itu, properti warisan harus didaftarkan sebagai properti terlampir, dan Anda harus mengikuti pola ini jika Anda ingin menentukan properti dependensi kustom dengan perilaku warisan properti. Hierarki yang tepat yang digunakan untuk pewarisan properti tidak dapat sepenuhnya diantisipasi oleh metode utilitas kelas pembantu, bahkan pada waktu eksekusi. Untuk informasi selengkapnya, lihat Pewarisan Nilai Properti.

Pohon Visual

Selain konsep pohon logis, ada juga konsep pohon visual di WPF. Pohon visual menjelaskan struktur objek visual, seperti yang diwakili oleh kelas dasar Visual. Saat Anda menulis templat untuk kontrol, Anda menentukan atau mendefinisikan ulang pohon visual yang berlaku untuk kontrol tersebut. Pohon visual juga menarik bagi pengembang yang menginginkan kontrol tingkat bawah atas gambar karena alasan performa dan pengoptimalan. Salah satu paparan pohon visual sebagai bagian dari pemrograman aplikasi WPF konvensional adalah bahwa rute peristiwa untuk peristiwa yang dirutekan sebagian besar melakukan perjalanan di sepanjang pohon visual, bukan pohon logis. Nuansa dari perilaku event yang dirutekan ini mungkin tidak langsung terlihat kecuali Anda adalah pengembang kontrol. Merutekan peristiwa melalui pohon visual memungkinkan kontrol yang menerapkan komposisi di tingkat visual untuk menangani peristiwa atau membuat setter peristiwa.

Pohon, Elemen Konten, dan Penyedia Konten

Elemen konten (kelas yang berasal dari ContentElement) bukan bagian dari pohon visual; mereka tidak mewarisi dari Visual dan tidak memiliki representasi visual. Agar dapat muncul sama sekali di antarmuka pengguna, ContentElement harus dihosting dalam host konten yang merupakan Visual sekaligus peserta dalam pohon logis. Biasanya objek seperti itu adalah FrameworkElement. Anda dapat mengonsepkan bahwa host konten agak seperti "browser" untuk konten dan memilih cara menampilkan konten tersebut dalam wilayah layar yang dikontrol host. Ketika konten dihosting, konten dapat menjadi bagian dalam proses pohon tertentu yang biasanya terkait dengan pohon visual. Umumnya, kelas host FrameworkElement mencakup kode implementasi yang menambahkan ContentElement yang dihosting ke rute peristiwa melalui subnode pohon logis konten, meskipun konten yang dihosting bukan bagian dari pohon visual sejati. Ini diperlukan agar ContentElement dapat memicu suatu peristiwa yang diarahkan ke elemen mana pun selain dirinya sendiri.

Penelusuran Pohon

Kelas LogicalTreeHelper menyediakan metode GetChildren, GetParent, dan FindLogicalNode untuk traversal pohon logis. Dalam kebanyakan kasus, Anda tidak harus melintasi pohon logis kontrol yang ada, karena kontrol ini hampir selalu mengekspos elemen anak logis mereka sebagai properti koleksi khusus yang mendukung akses pengumpulan seperti Add, pengindeks, dan sebagainya. Traversal pohon terutama merupakan skenario yang digunakan oleh pengembang kontrol yang memilih untuk tidak menggunakan pola kontrol yang sudah ada seperti ItemsControl atau Panel di mana properti koleksi sudah ditentukan, dan yang bermaksud untuk memberikan dukungan properti koleksi mereka sendiri.

Pohon visual juga mendukung kelas pembantu untuk traversal pohon visual, VisualTreeHelper. Pohon visual tidak secara mudah diekspos melalui properti spesifik kontrol, jadi kelas VisualTreeHelper adalah cara yang disarankan untuk melintasi pohon visual jika diperlukan untuk skenario pemrograman Anda. Untuk informasi selengkapnya, lihat Gambaran Umum Penyajian Grafis WPF .

Nota

Terkadang perlu memeriksa struktur visual templat yang diterapkan. Anda harus berhati-hati saat menggunakan teknik ini. Bahkan jika Anda melintasi pohon visual untuk kontrol tempat Anda menentukan templat, konsumen kontrol Anda selalu dapat mengubah templat dengan mengatur properti Template pada instans, dan bahkan pengguna akhir dapat memengaruhi templat yang diterapkan dengan mengubah tema sistem.

Rute untuk Peristiwa Yang Dirutekan sebagai "Pohon"

Seperti yang disebutkan sebelumnya, rute setiap peristiwa yang dirutekan berjalan di sepanjang satu jalur pohon yang telah ditentukan sebelumnya dan merupakan gabungan dari representasi pohon visual dan logis. Rute peristiwa dapat bergerak menuju ke atas atau ke bawah dalam hierarki pohon, tergantung apakah itu peristiwa yang dirutekan dengan cara terowongan atau menggelegak. Konsep rute peristiwa tidak memiliki kelas pembantu pendukung langsung yang dapat digunakan untuk "berjalan" rute peristiwa secara independen dari menaikkan peristiwa yang benar-benar rute. Ada kelas yang mewakili rute, EventRoute, tetapi metode kelas tersebut umumnya hanya untuk penggunaan internal.

Kamus dan Pohon Sumber Daya

Pencarian kamus sumber daya untuk semua Resources yang ditentukan dalam halaman pada dasarnya melintasi pohon logis. Objek yang tidak berada di pohon logis dapat mereferensikan sumber daya yang di-key, tetapi urutan pencarian sumber daya dimulai pada titik di mana objek tersebut terhubung ke pohon logis. Di WPF, hanya simpul pohon logis yang dapat memiliki properti Resources yang berisi ResourceDictionary, oleh karena itu menelusuri pohon visual untuk mencari sumber daya yang diberi kunci dari ResourceDictionarytidak bermanfaat.

Namun, pencarian sumber daya juga dapat meluas di luar pohon logis langsung. Untuk markup aplikasi, pencarian sumber daya kemudian dapat dilanjutkan ke kamus sumber daya tingkat aplikasi dan kemudian ke dukungan tema dan nilai sistem yang dirujuk sebagai properti statis atau kunci. Tema itu sendiri juga dapat mereferensikan nilai sistem di luar pohon logis tema jika referensi sumber daya dinamis. Untuk informasi selengkapnya tentang kamus sumber daya dan logika pencarian, lihat Sumber Daya XAML.

Lihat juga