Bagikan melalui


XAML dan Kelas Kustom untuk WPF

XAML seperti yang diimplementasikan dalam kerangka kerja common language runtime (CLR) mendukung kemampuan untuk menentukan kelas atau struktur kustom dalam bahasa umum runtime bahasa umum (CLR), lalu mengakses kelas tersebut menggunakan markup XAML. Anda dapat menggunakan campuran tipe yang ditentukan Windows Presentation Foundation (WPF) dan jenis kustom Anda dalam file markup yang sama, biasanya dengan memetakan jenis kustom ke awalan namespace XAML. Topik ini membahas persyaratan yang harus dipenuhi kelas kustom agar dapat digunakan sebagai elemen XAML.

Kelas Kustom di Aplikasi atau Rakitan

Kelas kustom yang digunakan dalam XAML dapat didefinisikan dengan dua cara berbeda: dalam kode di belakang atau kode lain yang menghasilkan aplikasi Windows Presentation Foundation (WPF) utama, atau sebagai kelas dalam rakitan terpisah, seperti eksekusi atau DLL yang digunakan sebagai pustaka kelas. Masing-masing pendekatan ini memiliki kelebihan dan kekurangan tertentu.

  • Keuntungan membuat pustaka kelas adalah bahwa kelas kustom tersebut dapat dibagikan di berbagai aplikasi yang mungkin. Pustaka terpisah juga membuat masalah penerapan versi aplikasi lebih mudah dikontrol, dan menyederhanakan pembuatan kelas di mana penggunaan kelas yang dimaksudkan adalah sebagai elemen akar pada halaman XAML.

  • Keuntungan mendefinisikan kelas kustom dalam aplikasi adalah bahwa teknik ini relatif ringan dan meminimalkan masalah penyebaran dan pengujian yang dihadapi ketika Anda memperkenalkan rakitan terpisah di luar aplikasi utama yang dapat dieksekusi.

  • Baik didefinisikan dalam rakitan yang sama atau berbeda, kelas kustom perlu dipetakan antara namespace CLR dan namespace XML untuk digunakan dalam XAML sebagai elemen. Lihat Namespace Layanan XAML dan Pemetaan Namespace layanan untuk WPF XAML.

Persyaratan untuk Kelas Kustom sebagai Elemen XAML

Agar dapat dibuat sebagai elemen objek, kelas Anda harus memenuhi persyaratan berikut:

  • Kelas kustom Anda harus publik dan mendukung konstruktor publik default (tanpa parameter). (Lihat bagian berikut untuk catatan mengenai struktur.)

  • Kelas kustom Anda tidak boleh menjadi kelas berlapis. Kelas berlapis dan "titik" dalam sintaks penggunaan CLR umumnya mengganggu fitur WPF dan/atau XAML lainnya seperti properti terlampir.

Selain mengaktifkan sintaks elemen objek, definisi objek Anda juga mengaktifkan sintaks elemen properti untuk properti publik lainnya yang mengambil objek tersebut sebagai jenis nilai. Ini karena objek sekarang dapat dibuat sebagai elemen objek dan dapat mengisi nilai elemen properti dari properti tersebut.

Struktur

Struktur yang Anda tentukan sebagai jenis kustom selalu dapat dibangun di XAML di WPF . Ini karena pengkompilasi CLR secara implisit membuat konstruktor tanpa parameter untuk struktur yang menginisialisasi semua nilai properti ke defaultnya. Dalam beberapa kasus, perilaku konstruksi default dan/atau penggunaan elemen objek untuk struktur tidak diinginkan. Ini mungkin karena struktur dimaksudkan untuk mengisi nilai dan berfungsi secara konseptual sebagai penyatuan, di mana nilai yang terkandung mungkin memiliki interpretasi yang saling eksklusif dan dengan demikian tidak ada propertinya yang dapat diatur. Contoh WPF dari struktur seperti itu adalah GridLength. Umumnya, struktur tersebut harus mengimplementasikan pengonversi jenis sehingga nilai dapat diekspresikan dalam bentuk atribut, menggunakan konvensi string yang membuat interpretasi atau mode nilai struktur yang berbeda. Struktur juga harus mengekspos perilaku serupa untuk konstruksi kode melalui konstruktor non-parameterless.

Persyaratan untuk Properti Kelas Kustom sebagai Atribut XAML

Properti harus mereferensikan jenis menurut nilai (seperti primitif), atau menggunakan kelas untuk jenis yang memiliki konstruktor tanpa parameter atau pengonversi jenis khusus yang dapat diakses prosesor XAML. Dalam implementasi CLR XAML, prosesor XAML menemukan pengonversi tersebut melalui dukungan asli untuk primitif bahasa, atau melalui penerapan TypeConverterAttribute ke jenis atau anggota dalam definisi jenis pendukung

Atau, properti dapat mereferensikan jenis kelas abstrak, atau antarmuka. Untuk kelas atau antarmuka abstrak, harapan untuk penguraian XAML adalah bahwa nilai properti harus diisi dengan instans kelas praktis yang mengimplementasikan antarmuka, atau instans jenis yang berasal dari kelas abstrak.

Properti dapat dideklarasikan pada kelas abstrak, tetapi hanya dapat diatur pada kelas praktis yang berasal dari kelas abstrak. Ini karena membuat elemen objek untuk kelas sama sekali memerlukan konstruktor tanpa parameter publik pada kelas .

Sintaks Atribut Berkemampuan TypeConverter

Jika Anda menyediakan pengonversi jenis khusus yang diatribusikan di tingkat kelas, konversi jenis yang diterapkan memungkinkan sintaks atribut untuk properti apa pun yang perlu membuat instans jenis tersebut. Pengonversi jenis tidak mengaktifkan penggunaan elemen objek dari jenis; hanya kehadiran konstruktor tanpa parameter untuk jenis tersebut yang memungkinkan penggunaan elemen objek. Oleh karena itu, properti yang diaktifkan type-converter umumnya tidak dapat digunakan dalam sintaks properti, kecuali jenis itu sendiri juga mendukung sintaks elemen objek. Pengecualian untuk ini adalah Anda dapat menentukan sintaks elemen properti, tetapi memiliki elemen properti yang berisi string. Penggunaan itu pada dasarnya setara dengan penggunaan sintaks atribut, dan penggunaan seperti itu tidak umum kecuali ada kebutuhan untuk penanganan spasi putih yang lebih kuat dari nilai atribut. Misalnya, berikut ini adalah penggunaan elemen properti yang mengambil string, dan penggunaan atribut yang setara:

<Button>Hallo!
  <Button.Language>
    de-DE
  </Button.Language>
</Button>
<Button Language="de-DE">Hallo!</Button>

Contoh properti di mana sintaks atribut diizinkan tetapi sintaks elemen properti yang berisi elemen objek tidak diizinkan melalui XAML adalah berbagai properti yang mengambil jenis.Cursor Kelas Cursor memiliki pengonversi CursorConverterjenis khusus , tetapi tidak mengekspos konstruktor tanpa parameter, sehingga Cursor properti hanya dapat diatur melalui sintaks atribut meskipun jenis aktual Cursor adalah jenis referensi.

Pengonversi Tipe Per Properti

Atau, properti itu sendiri dapat mendeklarasikan pengonversi jenis pada tingkat properti. Ini memungkinkan "bahasa mini" yang membuat instans objek dari jenis properti sebaris, dengan memproses nilai string masuk atribut sebagai input untuk ConvertFrom operasi berdasarkan jenis yang sesuai. Biasanya ini dilakukan untuk menyediakan aksesor kenyamanan, dan bukan sebagai satu-satunya cara untuk mengaktifkan pengaturan properti di XAML. Namun, dimungkinkan juga untuk menggunakan pengonversi jenis untuk atribut di mana Anda ingin menggunakan jenis CLR yang ada yang tidak menyediakan konstruktor tanpa parameter atau pengonversi jenis atribut. Contoh dari WPF API adalah properti tertentu yang mengambil jenisnya CultureInfo . Dalam hal ini, WPF menggunakan jenis Microsoft .NET Framework CultureInfo yang ada untuk mengatasi skenario kompatibilitas dan migrasi yang lebih baik yang digunakan dalam versi kerangka kerja sebelumnya, tetapi jenisnya CultureInfo tidak mendukung konstruktor yang diperlukan atau konversi jenis tingkat jenis agar dapat digunakan sebagai nilai properti XAML secara langsung.

Setiap kali Anda mengekspos properti yang memiliki penggunaan XAML, terutama jika Anda adalah penulis kontrol, Anda harus sangat mempertimbangkan untuk mendukung properti tersebut dengan properti dependensi. Ini terutama berlaku jika Anda menggunakan implementasi Windows Presentation Foundation (WPF) yang ada dari prosesor XAML, karena Anda dapat meningkatkan performa dengan menggunakan DependencyProperty backing. Properti dependensi akan mengekspos fitur sistem properti untuk properti Anda yang akan diharapkan pengguna untuk properti XAML yang dapat diakses. Ini termasuk fitur seperti animasi, pengikatan data, dan dukungan gaya. Untuk informasi selengkapnya, lihat Properti Dependensi Kustom dan Properti Pemuatan dan Dependensi XAML.

Menulis dan Attributing Pengonversi Tipe

Terkadang Anda perlu menulis kelas turunan kustom TypeConverter untuk memberikan konversi jenis untuk jenis properti Anda. Untuk instruksi tentang cara memperoleh dan membuat pengonversi jenis yang dapat mendukung penggunaan XAML, dan cara menerapkan TypeConverterAttribute, lihat TypeConverters dan XAML.

Persyaratan untuk Sintaks Atribut Penanganan Aktivitas XAML pada Peristiwa Kelas Kustom

Agar dapat digunakan sebagai peristiwa CLR, peristiwa harus diekspos sebagai peristiwa publik di kelas yang mendukung konstruktor tanpa parameter, atau pada kelas abstrak tempat peristiwa dapat diakses pada kelas turunan. Agar dapat digunakan dengan mudah sebagai peristiwa yang dirutekan, peristiwa CLR Anda harus menerapkan metode dan eksplisitadd, yang menambahkan dan menghapus handler untuk tanda tangan peristiwa CLR dan meneruskan handler tersebut ke AddHandler metode dan RemoveHandler .remove Metode ini menambahkan atau menghapus handler ke penyimpanan penanganan aktivitas yang dirutekan pada instans tempat peristiwa dilampirkan.

Catatan

Dimungkinkan untuk mendaftarkan handler secara langsung untuk peristiwa yang dirutekan menggunakan AddHandler, dan untuk secara sengaja tidak menentukan peristiwa CLR yang mengekspos peristiwa yang dirutekan. Ini umumnya tidak disarankan karena peristiwa tidak akan mengaktifkan sintaks atribut XAML untuk melampirkan handler, dan kelas yang dihasilkan akan menawarkan tampilan XAML yang kurang transparan dari kemampuan jenis tersebut.

Properti Koleksi Penulisan

Properti yang mengambil jenis koleksi memiliki sintaks XAML yang memungkinkan Anda menentukan objek yang ditambahkan ke koleksi. Sintaks ini memiliki dua fitur penting.

  • Objek yang merupakan objek koleksi tidak perlu ditentukan dalam sintaks elemen objek. Kehadiran jenis koleksi tersebut bersifat implisit setiap kali Anda menentukan properti di XAML yang mengambil jenis koleksi.

  • Elemen turunan dari properti koleksi dalam markup diproses untuk menjadi anggota koleksi. Biasanya, akses kode ke anggota koleksi dilakukan melalui metode daftar/kamus seperti Add, atau melalui pengindeks. Tetapi sintaks XAML tidak mendukung metode atau pengindeks (pengecualian: XAML 2009 dapat mendukung metode, tetapi menggunakan XAML 2009 membatasi kemungkinan penggunaan WPF; lihat Fitur Bahasa XAML 2009). Koleksi jelas merupakan persyaratan yang sangat umum untuk membangun pohon elemen, dan Anda memerlukan beberapa cara untuk mengisi koleksi ini dalam XAML deklaratif. Oleh karena itu, elemen turunan dari properti koleksi diproses dengan menambahkannya ke koleksi yang merupakan nilai jenis properti koleksi.

Implementasi Layanan XAML .NET Framework dan dengan demikian prosesor WPF XAML menggunakan definisi berikut untuk apa yang merupakan properti koleksi. Jenis properti properti harus mengimplementasikan salah satu hal berikut:

Masing-masing jenis ini di CLR memiliki Add metode, yang digunakan oleh prosesor XAML untuk menambahkan item ke koleksi yang mendasar saat membuat grafik objek.

Catatan

Generik List dan Dictionary antarmuka (IList<T> dan IDictionary<TKey,TValue>) tidak didukung untuk deteksi koleksi oleh prosesor WPF XAML. Namun, Anda dapat menggunakan List<T> kelas sebagai kelas dasar, karena mengimplementasikan IList secara langsung, atau Dictionary<TKey,TValue> sebagai kelas dasar, karena menerapkannya IDictionary secara langsung.

Saat Anda mendeklarasikan properti yang mengambil koleksi, berhati-hatilah tentang bagaimana nilai properti tersebut diinisialisasi dalam instans baru jenisnya. Jika Anda tidak menerapkan properti sebagai properti dependensi, maka meminta properti menggunakan bidang backing yang memanggil konstruktor jenis koleksi memadai. Jika properti Anda adalah properti dependensi, maka Anda mungkin perlu menginisialisasi properti koleksi sebagai bagian dari konstruktor jenis default. Ini karena properti dependensi mengambil nilai defaultnya dari metadata, dan Anda biasanya tidak ingin nilai awal properti koleksi menjadi koleksi bersama statis. Harus ada instans koleksi per masing-masing berisi instans jenis. Untuk informasi selengkapnya, lihat Properti Dependensi Kustom.

Anda dapat menerapkan jenis koleksi kustom untuk properti koleksi Anda. Karena perlakuan properti koleksi implisit, jenis koleksi kustom tidak perlu menyediakan konstruktor tanpa parameter untuk digunakan dalam XAML secara implisit. Namun, Anda dapat secara opsional menyediakan konstruktor tanpa parameter untuk jenis koleksi. Ini bisa menjadi praktik yang berharga. Kecuali Anda memberikan konstruktor tanpa parameter, Anda tidak dapat secara eksplisit mendeklarasikan koleksi sebagai elemen objek. Beberapa penulis markup mungkin lebih suka melihat koleksi eksplisit sebagai masalah gaya markup. Selain itu, konstruktor tanpa parameter dapat menyederhanakan persyaratan inisialisasi saat Anda membuat objek baru yang menggunakan jenis koleksi Anda sebagai nilai properti.

Mendeklarasikan Properti Konten XAML

Bahasa XAML mendefinisikan konsep properti konten XAML. Setiap kelas yang dapat digunakan dalam sintaks objek dapat memiliki satu properti konten XAML. Untuk mendeklarasikan properti menjadi properti konten XAML untuk kelas Anda, terapkan ContentPropertyAttribute sebagai bagian dari definisi kelas. Tentukan nama properti konten XAML yang dimaksudkan sebagai dalam Name atribut . Properti ditentukan sebagai string menurut nama, bukan sebagai konstruksi pantulan seperti PropertyInfo.

Anda dapat menentukan properti koleksi untuk menjadi properti konten XAML. Ini menghasilkan penggunaan untuk properti tersebut di mana elemen objek dapat memiliki satu atau beberapa elemen turunan, tanpa elemen objek koleksi atau tag elemen properti yang mengintervensi. Elemen-elemen ini kemudian diperlakukan sebagai nilai untuk properti konten XAML dan ditambahkan ke instans koleksi cadangan.

Beberapa properti konten XAML yang ada menggunakan jenis properti .Object Ini memungkinkan properti konten XAML yang dapat mengambil nilai primitif seperti String serta mengambil satu nilai objek referensi. Jika Anda mengikuti model ini, jenis Anda bertanggung jawab atas penentuan jenis serta penanganan jenis yang mungkin. Alasan umum untuk Object jenis konten adalah untuk mendukung cara sederhana menambahkan konten objek sebagai string (yang menerima perlakuan presentasi default), atau cara lanjutan untuk menambahkan konten objek yang menentukan presentasi non-default atau data tambahan.

Serialisasi XAML

Untuk skenario tertentu, seperti jika Anda adalah penulis kontrol, Anda mungkin juga ingin memastikan bahwa representasi objek apa pun yang dapat diinstansiasi di XAML juga dapat diserialisasikan kembali ke markup XAML yang setara. Persyaratan serialisasi tidak dijelaskan dalam topik ini. Lihat Gambaran Umum Penulisan Kontrol dan Pohon Elemen dan Serialisasi.

Baca juga