Bagikan melalui


Gambaran umum ekstensi markup untuk XAML

Ekstensi markup adalah teknik XAML untuk mendapatkan nilai yang bukan primitif atau jenis XAML tertentu. Untuk penggunaan atribut, ekstensi markup menggunakan urutan karakter yang diketahui dari kurung kurawal { pembuka untuk memasukkan cakupan ekstensi markup, dan kurung } kurawal penutup untuk keluar. Saat menggunakan Layanan XAML .NET, Anda dapat menggunakan beberapa ekstensi markup bahasa XAML yang telah ditentukan sebelumnya dari rakitan System.Xaml. Anda juga dapat subkelas dari MarkupExtension kelas, yang ditentukan dalam System.Xaml, dan menentukan ekstensi markup Anda sendiri. Atau Anda dapat menggunakan ekstensi markup yang ditentukan oleh kerangka kerja tertentu jika Anda sudah mereferensikan kerangka kerja tersebut.

Ketika penggunaan ekstensi markup diakses, penulis objek XAML dapat menyediakan layanan ke kelas kustom MarkupExtension melalui titik koneksi layanan dalam penimpaan MarkupExtension.ProvideValue . Layanan ini dapat digunakan untuk mendapatkan konteks tentang penggunaan, kemampuan khusus penulis objek, konteks skema XAML, dan sebagainya.

Ekstensi markup yang ditentukan XAML

Beberapa ekstensi markup diimplementasikan oleh Layanan XAML .NET untuk dukungan bahasa XAML. Ekstensi markup ini sesuai dengan bagian spesifikasi XAML sebagai bahasa. Ini biasanya dapat diidentifikasi oleh awalan x: dalam sintaks seperti yang terlihat dalam penggunaan umum. Implementasi Layanan XAML .NET untuk elemen bahasa XAML ini semuanya berasal dari MarkupExtension kelas dasar.

Catatan

x: Awalan digunakan untuk pemetaan namespace XAML khas namespace bahasa XAML, dalam elemen akar produksi XAML. Misalnya, proyek Visual Studio dan templat halaman untuk berbagai kerangka kerja tertentu memulai file XAML menggunakan pemetaan ini x: . Anda dapat memilih token awalan yang berbeda dalam pemetaan namespace XAML Anda sendiri, tetapi dokumentasi ini akan mengasumsikan pemetaan default x: sebagai sarana untuk mengidentifikasi entitas yang merupakan bagian yang ditentukan dari namespace XAML bahasa XAML, dibandingkan dengan namespace XAML default kerangka kerja tertentu atau namespace CLR atau XML arbitrer lainnya.

x:Type

x:TypeType memasok objek untuk jenis bernama. Fungsionalitas ini paling sering digunakan dalam mekanisme penundaan yang menggunakan jenis CLR yang mendasar dan jenis derivasi sebagai moniker pengelompokan atau pengidentifikasi. Gaya dan templat WPF, dan penggunaan TargetType propertinya, adalah contoh tertentu. Untuk informasi selengkapnya, lihat x:Type Markup Extension.

x:Static

x:Static menghasilkan nilai statis dari entitas kode jenis nilai yang tidak secara langsung merupakan jenis nilai properti, tetapi dapat dievaluasi ke jenis tersebut. Ini berguna untuk menentukan nilai yang sudah ada sebagai konstanta terkenal dalam definisi jenis. Untuk informasi selengkapnya, lihat x:Static Markup Extension.

x:Null

x:Nullnull menentukan sebagai nilai untuk anggota XAML. Bergantung pada desain jenis tertentu atau pada konsep kerangka kerja yang lebih besar, null tidak selalu merupakan nilai default untuk properti, atau nilai tersirat dari atribut string kosong. Untuk informasi selengkapnya, lihat x:Null Markup Extension.

x:Array

x:Array mendukung pembuatan array umum dalam sintaks XAML dalam kasus di mana dukungan koleksi yang disediakan oleh elemen dasar dan model kontrol sengaja tidak digunakan. Untuk informasi selengkapnya, lihat x:Array Markup Extension. Dalam XAML 2009 secara khusus, array diakses sebagai primitif bahasa alih-alih sebagai ekstensi. Untuk informasi selengkapnya, lihat Fitur Bahasa XAML 2009.

x:Reference

x:Reference adalah bagian dari XAML 2009, ekstensi set bahasa asli (2006). x:Reference mewakili referensi ke objek lain yang ada dalam grafik objek. Objek itu diidentifikasi oleh x:Name. Untuk informasi selengkapnya, lihat x:Reference Markup Extension.

Konstruksi x lainnya

Konstruksi lain x: untuk mendukung fitur bahasa XAML ada, tetapi ini tidak diimplementasikan sebagai ekstensi markup. Untuk informasi lebih lanjut, lihat XAML Namespace (x:) Fitur Bahasa.

Kelas Dasar MarkupExtension

Untuk menentukan ekstensi markup kustom yang dapat berinteraksi dengan implementasi default pembaca XAML dan penulis XAML di System.Xaml, Anda memperoleh kelas dari kelas abstrak MarkupExtension . Kelas itu memiliki satu metode untuk mengambil alih, yaitu ProvideValue. Anda mungkin juga perlu menentukan konstruktor tambahan untuk mendukung argumen ke penggunaan ekstensi markup, dan mencocokkan properti yang dapat diatur.

Melalui ProvideValue, ekstensi markup kustom memiliki akses ke konteks layanan yang melaporkan lingkungan tempat ekstensi markup dipanggil oleh prosesor XAML. Di jalur beban, biasanya ini adalah XamlObjectWriter. Di jalur penyimpanan, biasanya ini adalah XamlXmlWriter. Setiap melaporkan konteks layanan sebagai kelas konteks penyedia layanan XAML internal yang menerapkan pola penyedia layanan. Untuk informasi selengkapnya tentang layanan yang tersedia dan apa yang diwakilinya, lihat Jenis Pengonversi dan Ekstensi Markup untuk XAML.

Kelas ekstensi markup Anda harus menggunakan tingkat akses publik; Prosesor XAML harus selalu dapat membuat instans kelas dukungan ekstensi markup untuk menggunakan layanannya.

Menentukan Jenis Dukungan untuk Ekstensi Markup Kustom

Saat Anda menggunakan .NET XAML Services atau kerangka kerja yang dibangun di .NET XAML Services, Anda memiliki dua pilihan tentang cara memberi nama jenis dukungan ekstensi markup. Nama jenis relevan dengan bagaimana penulis objek XAML mencoba mengakses dan memanggil jenis dukungan ekstensi markup ketika mereka menemukan penggunaan ekstensi markup di XAML. Gunakan salah satu strategi penamaan berikut:

  • Beri nama jenis agar sama persis dengan token penggunaan markup XAML. Misalnya, untuk mendukung {Collate ...} penggunaan ekstensi, beri nama jenis Collatedukungan .
  • Beri nama jenis untuk menjadi token string penggunaan ditambah akhiran Extension. Misalnya, untuk mendukung {Collate ...} penggunaan ekstensi, beri nama jenis CollateExtensiondukungan .

Urutan pencarian adalah mencari Extensionnama kelas -akhiran terlebih dahulu dan kemudian mencari nama kelas tanpa akhiran Extension .

Dari perspektif penggunaan markup, termasuk Extension akhiran sebagai bagian dari penggunaan valid. Namun, ini berperilaku seolah-olah Extension benar-benar bagian dari nama kelas, dan penulis objek XAML akan gagal menyelesaikan kelas dukungan ekstensi markup untuk penggunaan tersebut jika kelas dukungan tidak memiliki Extension akhiran.

Konstruktor tanpa parameter

Untuk semua jenis dukungan ekstensi markup, Anda harus mengekspos konstruktor tanpa parameter publik. Konstruktor tanpa parameter diperlukan untuk setiap kasus di mana penulis objek XAML membuat instans ekstensi markup dari penggunaan elemen objek. Mendukung penggunaan elemen objek adalah harapan yang adil untuk ekstensi markup, terutama untuk serialisasi. Namun, Anda dapat menerapkan ekstensi markup tanpa konstruktor publik jika Anda hanya ingin mendukung penggunaan atribut ekstensi markup.

Jika penggunaan ekstensi markup Anda tidak memiliki argumen, konstruktor tanpa parameter diperlukan untuk mendukung penggunaan.

Pola Konstruktor dan Argumen Posisi untuk Ekstensi Markup Kustom

Untuk ekstensi markup dengan penggunaan argumen yang dimaksudkan, konstruktor publik harus sesuai dengan mode penggunaan yang dimaksudkan. Dengan kata lain, jika ekstensi markup Anda dirancang untuk memerlukan satu argumen posisi sebagai penggunaan yang valid, Anda harus mendukung konstruktor publik dengan satu parameter input yang mengambil argumen posisional.

Misalnya, Collate ekstensi markup dimaksudkan untuk hanya mendukung mode di mana ada satu argumen posisi yang mewakili modenya, yang ditentukan sebagai CollationMode konstanta enumerasi. Dalam hal ini, harus ada konstruktor dengan formulir berikut:

public Collate(CollationMode collationMode) {...}

Pada tingkat dasar, argumen yang diteruskan ke ekstensi markup adalah string karena sedang diteruskan dari nilai atribut markup. Anda dapat membuat semua string argumen Anda dan bekerja dengan input pada tingkat tersebut. Namun, Anda memiliki akses ke pemrosesan tertentu yang terjadi sebelum argumen ekstensi markup diteruskan ke kelas dukungan.

Pemrosesan bekerja secara konseptual seolah-olah ekstensi markup adalah objek yang akan dibuat, lalu nilai anggotanya diatur. Setiap properti yang ditentukan untuk diatur dievaluasi mirip dengan bagaimana anggota tertentu dapat diatur pada objek yang dibuat saat XAML diurai. Ada dua perbedaan penting:

  • Seperti disebutkan sebelumnya, jenis dukungan ekstensi markup tidak perlu memiliki konstruktor tanpa parameter untuk dibuat di XAML. Konstruksi objeknya ditangguhkan sampai argumen yang mungkin dalam sintaks teks ditokenisasi dan dievaluasi sebagai argumen posisi atau bernama, dan konstruktor yang sesuai dipanggil pada saat itu.
  • Penggunaan ekstensi markup dapat ditumpuk. Ekstensi markup paling dalam dievaluasi terlebih dahulu. Oleh karena itu, Anda dapat mengasumsikan penggunaan seperti itu dan menyatakan salah satu parameter konstruksi menjadi jenis yang memerlukan pengonversi nilai (seperti ekstensi markup) untuk diproduksi.

Keterganian pada pemrosesan tersebut ditunjukkan dalam contoh sebelumnya. Penulis objek XAML Layanan XAML .NET memproses nama konstanta enumerasi menjadi nilai enumerasi pada tingkat asli.

Memproses sintaks teks parameter posisi ekstensi markup juga dapat mengandalkan pengonversi jenis yang terkait dengan jenis yang ada dalam argumen konstruksi.

Argumen disebut argumen posisional karena urutan di mana token dalam penggunaan ditemui sesuai dengan urutan posisi parameter konstruktor tempat mereka ditetapkan. Misalnya, pertimbangkan tanda tangan konstruktor berikut:

public Collate(CollationMode collationMode, object collateThis) {...}

Prosesor XAML mengharapkan dua argumen posisi untuk ekstensi markup ini. Jika ada penggunaan {Collate AlphaUp,{x:Reference circularFile}}, AlphaUp token dikirim ke parameter pertama dan dievaluasi sebagai CollationMode enumerasi bernama konstanta. Hasil dari bagian dalam x:Reference dikirim ke parameter kedua dan dievaluasi sebagai objek.

Dalam aturan yang ditentukan XAML untuk sintaks dan pemrosesan ekstensi markup, koma adalah pemisah antara argumen, apakah argumen tersebut adalah argumen posisi atau argumen bernama.

Aritas duplikat argumen posisional

Jika penulis objek XAML mengalami penggunaan ekstensi markup dengan argumen posisional, dan ada beberapa argumen konstruktor yang mengambil jumlah argumen tersebut (aritas duplikat), itu belum tentu merupakan kesalahan. Perilaku tergantung pada pengaturan konteks skema XAML yang dapat disesuaikan, SupportMarkupExtensionsWithDuplicateArity. Jika SupportMarkupExtensionsWithDuplicateArity adalah true, penulis objek XAML tidak boleh melempar pengecualian hanya karena alasan aritas duplikat. Perilaku di luar titik itu tidak didefinisikan secara ketat. Asumsi desain dasar adalah bahwa konteks skema memiliki informasi jenis yang tersedia untuk parameter tertentu dan dapat mencoba cast eksplisit yang cocok dengan kandidat duplikat untuk melihat tanda tangan mana yang mungkin paling cocok. Pengecualian mungkin masih dilemparkan jika tidak ada tanda tangan yang dapat melewati pengujian yang diberlakukan oleh konteks skema tertentu yang berjalan pada penulis objek XAML.

Secara default, SupportMarkupExtensionsWithDuplicateArity berada false di berbasis XamlSchemaContext CLR untuk Layanan XAML .NET. Dengan demikian, default XamlObjectWriter melemparkan pengecualian jika mengalami penggunaan ekstensi markup di mana ada aritas duplikat di konstruktor jenis backing.

Argumen bernama untuk ekstensi markup kustom

Ekstensi markup seperti yang ditentukan oleh XAML juga dapat menggunakan formulir argumen bernama untuk penggunaan. Pada tingkat tokenisasi pertama, sintaks teks dibagi menjadi argumen. Kehadiran tanda sama dengan (=) dalam argumen apa pun mengidentifikasi argumen sebagai argumen bernama. Argumen seperti itu juga ditokenisasi ke dalam pasangan nama/nilai. Nama dalam kasus ini menamai properti yang dapat diatur publik dari jenis dukungan ekstensi markup. Jika Anda ingin mendukung penggunaan argumen bernama, Anda harus menyediakan properti yang dapat diatur publik ini. Properti dapat diwariskan properti selama tetap publik.

Mengakses Konteks Penyedia Layanan dari Implementasi Ekstensi Markup

Layanan yang tersedia sama untuk pengonversi nilai apa pun. Perbedaannya adalah bagaimana setiap pengonversi nilai menerima konteks layanan. Mengakses layanan dan layanan yang tersedia didokumenkan dalam topik Jenis Pengonversi dan Ekstensi Markup untuk XAML.

Penggunaan elemen properti dari ekstensi markup

Skenario untuk penggunaan ekstensi markup sering dirancang menggunakan ekstensi markup dalam penggunaan atribut. Namun, berpotensi juga untuk menentukan kelas pendukung untuk mendukung penggunaan elemen properti.

Untuk mendukung penggunaan elemen properti ekstensi markup Anda, tentukan konstruktor tanpa parameter publik. Ini harus menjadi konstruktor instans bukan konstruktor statis. Ini diperlukan karena prosesor XAML umumnya harus memanggil konstruktor tanpa parameter pada elemen objek apa pun yang diprosesnya dari markup, dan ini termasuk kelas ekstensi markup sebagai elemen objek. Untuk skenario lanjutan, Anda dapat menentukan jalur konstruksi non-default untuk kelas. (Untuk informasi selengkapnya, lihat x:FactoryMethod Directive.) Namun, Anda tidak boleh menggunakan pola ini untuk tujuan ekstensi markup karena ini membuat penemuan pola penggunaan jauh lebih sulit, baik untuk desainer maupun untuk pengguna markup mentah.

Attributing untuk ekstensi markup kustom

Untuk mendukung lingkungan desain dan skenario penulis objek XAML tertentu, Anda harus mengaitkan jenis dukungan ekstensi markup dengan beberapa atribut CLR. Atribut ini melaporkan penggunaan ekstensi markup yang dimaksudkan.

MarkupExtensionReturnTypeAttributeType melaporkan informasi untuk jenis objek yang ProvideValue dikembalikan. Dengan tanda tangan murninya, ProvideValue mengembalikan Object. Tetapi berbagai konsumen mungkin menginginkan informasi jenis pengembalian yang lebih tepat. Drive ini termasuk:

  • Desainer dan IDEs, yang mungkin dapat memberikan dukungan sadar jenis untuk penggunaan ekstensi markup.
  • Implementasi lanjutan SetMarkupExtension handler pada kelas target, yang mungkin mengandalkan refleksi untuk menentukan jenis pengembalian ekstensi markup alih-alih bercabang pada implementasi tertentu yang diketahui MarkupExtension berdasarkan nama.

Serialisasi penggunaan ekstensi markup

Ketika penulis objek XAML memproses penggunaan ekstensi markup dan memanggil ProvideValue, konteks untuk itu sebelumnya adalah penggunaan ekstensi markup tetap ada di aliran simpul XAML tetapi tidak dalam grafik objek. Dalam grafik objek, hanya nilai yang dipertahankan. Jika Anda memiliki skenario desain atau alasan lain untuk mempertahankan penggunaan ekstensi markup asli ke dalam output berseri, Anda harus merancang infrastruktur Anda sendiri untuk melacak penggunaan ekstensi markup dari aliran simpul XAML jalur beban. Anda dapat menerapkan perilaku untuk membuat ulang elemen aliran simpul dari jalur beban dan memutarnya kembali ke penulis XAML untuk serialisasi di jalur penyimpanan, menggantikan nilai dalam posisi aliran simpul yang sesuai.

Ekstensi markup di aliran simpul XAML

Jika Anda bekerja dengan aliran simpul XAML di jalur beban, penggunaan ekstensi markup muncul di aliran simpul sebagai objek.

Jika penggunaan ekstensi markup menggunakan argumen posisional, maka akan direpresentasikan sebagai objek awal dengan nilai inisialisasi. Sebagai representasi teks kasar, aliran simpul menyerupan sebagai berikut:

StartObject (XamlType adalah jenis definisi ekstensi markup, bukan jenis pengembaliannya)

StartMember (nama XamlMember adalah _InitializationText)

Value (nilai adalah argumen posisi sebagai string termasuk pemisah intervensi)

EndMember

EndObject

Penggunaan ekstensi markup dengan argumen bernama direpresentasikan sebagai objek dengan anggota nama yang relevan, masing-masing diatur dengan nilai string teks.

Sebenarnya memanggil ProvideValue implementasi ekstensi markup memerlukan konteks skema XAML karena memerlukan pemetaan jenis dan pembuatan instans jenis dukungan ekstensi markup. Ini adalah salah satu alasan mengapa penggunaan ekstensi markup dipertahankan dengan cara ini dalam aliran simpul .NET XAML Services default - bagian pembaca dari jalur beban sering tidak memiliki konteks skema XAML yang diperlukan yang tersedia.

Jika Anda bekerja dengan aliran simpul XAML di jalur penyimpanan, umumnya tidak ada yang ada dalam representasi grafik objek yang dapat memberi tahu Anda bahwa objek untuk diserialisasikan awalnya disediakan oleh penggunaan ekstensi markup dan ProvideValue hasilnya. Skenario yang perlu mempertahankan penggunaan ekstensi markup untuk round-tripping sekaligus menangkap perubahan lain dalam grafik objek harus merancang teknik mereka sendiri untuk mempertahankan pengetahuan tentang penggunaan ekstensi markup dari input XAML asli. Misalnya, untuk memulihkan penggunaan ekstensi markup, Anda mungkin perlu bekerja dengan aliran simpul pada jalur penyimpanan untuk memulihkan penggunaan ekstensi markup, atau melakukan beberapa jenis penggabungan antara XAML asli dan XAML dua arah. Beberapa kerangka kerja penerapan XAML seperti WPF menggunakan jenis perantara (ekspresi) untuk membantu mewakili kasus di mana penggunaan ekstensi markup menyediakan nilai.

Baca juga