Bagikan melalui


Sintaks XAML secara rinci

Topik ini mendefinisikan istilah yang digunakan untuk menggambarkan elemen sintaks XAML. Istilah-istilah ini sering digunakan di seluruh sisa dokumentasi ini, baik untuk dokumentasi WPF secara khusus maupun untuk kerangka kerja lain yang menggunakan XAML atau konsep XAML dasar yang diaktifkan oleh dukungan bahasa XAML di tingkat System.Xaml. Topik ini diperluas pada terminologi dasar yang diperkenalkan dalam topik XAML di WPF.

Spesifikasi Bahasa XAML

Terminologi sintaks XAML yang ditentukan di sini juga ditentukan atau dirujuk dalam spesifikasi bahasa XAML. XAML adalah bahasa berdasarkan XML dan mengikuti atau memperluas aturan struktural XML. Beberapa terminologi dibagikan dari atau didasarkan pada terminologi yang umum digunakan saat menjelaskan bahasa XML atau model objek dokumen XML.

Untuk informasi selengkapnya tentang spesifikasi bahasa XAML, unduh [MS-XAML] dari Pusat Unduhan Microsoft.

XAML dan CLR

XAML adalah bahasa markup. Lingkungan waktu proses umum (CLR), seperti yang dijelaskan oleh namanya, memungkinkan pelaksanaan waktu proses. XAML bukan dengan sendirinya salah satu bahasa umum yang langsung dikonsumsi oleh runtime CLR. Sebagai gantinya, Anda dapat menganggap XAML sebagai pendukung sistem jenisnya sendiri. Sistem penguraian XAML tertentu yang digunakan oleh WPF dibangun pada CLR dan sistem jenis CLR. Jenis XAML dipetakan ke jenis CLR untuk menginisiasi representasi runtime ketika XAML untuk WPF diparsing. Untuk alasan ini, sisa diskusi sintaksis dalam dokumen ini akan mencakup referensi ke sistem jenis CLR, meskipun diskusi sintaksis yang setara dalam spesifikasi bahasa XAML tidak. (Sesuai tingkat spesifikasi bahasa XAML, jenis XAML dapat dipetakan ke sistem jenis lain, yang tidak harus CLR, tetapi itu akan memerlukan pembuatan dan penggunaan parser XAML yang berbeda.)

Anggota Tipe dan Pewarisan Kelas

Properti dan event ketika muncul sebagai anggota XAML dari tipe WPF sering diwarisi dari tipe dasar. Misalnya, pertimbangkan contoh ini: <Button Background="Blue" .../>. Properti Background bukan properti yang langsung dideklarasikan pada kelas Button, jika Anda melihat definisi kelas, hasil refleksi, atau dokumentasinya. Sebaliknya, Background diwarisi dari kelas Control dasar.

Perilaku pewarisan kelas elemen WPF XAML adalah kepergian yang signifikan dari interpretasi markup XML yang diberlakukan skema. Warisan kelas dapat menjadi kompleks, terutama ketika kelas dasar perantara abstrak, atau ketika antarmuka terlibat. Ini adalah salah satu alasan bahwa set elemen XAML dan atribut yang diizinkan sulit untuk mewakili secara akurat dan sepenuhnya menggunakan jenis skema yang biasanya digunakan untuk pemrograman XML, seperti format DTD atau XSD. Alasan lain adalah bahwa fitur ekstensibilitas dan pemetaan jenis bahasa XAML itu sendiri menghalangi kelengkapan representasi tetap dari jenis dan anggota yang diizinkan.

Sintaks Elemen Objek

Sintaks elemen Object adalah sintaks markup XAML yang membuat instans kelas atau struktur CLR dengan mendeklarasikan elemen XML. Sintaks ini menyerupai sintaks elemen dari bahasa markup lain seperti HTML. Sintaks elemen objek dimulai dengan tanda kurung sudut kiri (<), diikuti segera dengan nama jenis kelas atau struktur yang sedang dibuat. Nol atau lebih spasi dapat mengikuti nama jenis, dan nol atau lebih atribut juga dapat dideklarasikan pada elemen objek, dengan satu atau beberapa spasi yang memisahkan setiap pasangan nama atribut="nilai". Akhirnya, salah satu hal berikut ini harus benar:

  • Elemen dan tag harus ditutup dengan garis miring ke depan (/) diikuti segera dengan tanda kurung sudut kanan (>).

  • Tag pembuka harus diselesaikan dengan tanda kurung sudut kanan (>). Elemen objek lainnya, elemen properti, atau teks dalam, dapat mengikuti tag pembuka. Konten apa yang mungkin terkandung di sini biasanya dibatasi oleh model objek elemen. Tag penutup yang setara untuk elemen objek juga harus ada, dalam sarang dan keseimbangan yang tepat dengan pasangan tag pembuka dan penutup lainnya.

XAML seperti yang diimplementasikan oleh .NET memiliki sekumpulan aturan yang memetakan elemen objek ke dalam jenis, atribut ke dalam properti atau peristiwa, dan namespace XAML ke namespace CLR ditambah assembly. Untuk WPF dan .NET, elemen objek XAML dipetakan ke tipe .NET seperti yang didefinisikan dalam rakitan yang dirujuk, dan atribut dipetakan ke anggota dari tipe tersebut. Ketika Anda mereferensikan jenis CLR di XAML, Anda juga memiliki akses ke anggota yang diwariskan dari jenis tersebut.

Misalnya, contoh berikut adalah sintaks elemen objek yang membuat instans baru dari kelas Button, dan juga menentukan atribut Name dan nilai untuk atribut tersebut:

<Button Name="CheckoutButton"/>

Contoh berikut adalah sintaks elemen objek yang juga menyertakan sintaks properti konten XAML. Teks yang terdapat di dalamnya akan digunakan untuk menetapkan properti konten XAML TextBox, Text.

<TextBox>This is a Text Box</TextBox>

Model Konten

Kelas mungkin mendukung penggunaan sebagai elemen objek XAML dalam hal sintaks, tetapi elemen tersebut hanya akan berfungsi dengan baik di aplikasi atau halaman ketika ditempatkan dalam posisi yang diharapkan dari model konten keseluruhan atau pohon elemen. Misalnya, MenuItem biasanya hanya boleh ditempatkan sebagai anak dari kelas turunan MenuBase seperti Menu. Model konten untuk elemen tertentu didokumentasikan sebagai bagian dari keterangan pada halaman kelas untuk kontrol dan kelas WPF lainnya yang dapat digunakan sebagai elemen XAML.

Properti Elemen Objek

Properti di XAML diatur oleh berbagai sintaks yang mungkin. Sintaks mana yang dapat digunakan untuk properti tertentu akan bervariasi, berdasarkan karakteristik sistem jenis yang mendasar dari properti yang Anda atur.

Dengan mengatur nilai properti, Anda menambahkan fitur atau karakteristik ke objek seperti yang ada di grafik objek run time. Status awal objek yang dibuat dari elemen objek didasarkan pada perilaku konstruktor tanpa parameter. Biasanya, aplikasi Anda akan menggunakan sesuatu selain instans default sepenuhnya dari objek tertentu.

Sintaksis Atribut (Properti)

Sintaks atribut adalah sintaks markup XAML yang mengatur nilai untuk properti dengan mendeklarasikan atribut pada elemen objek yang ada. Nama atribut harus cocok dengan nama anggota CLR dari properti kelas yang mendukung elemen objek yang relevan. Nama atribut diikuti oleh operator penugasan (=). Nilai atribut harus berupa string yang diapit dalam tanda kutip.

Nota

Anda dapat menggunakan tanda kutip alternatif untuk menempatkan tanda kutip harfiah dalam atribut. Misalnya Anda dapat menggunakan tanda kutip tunggal sebagai sarana untuk mendeklarasikan string yang berisi karakter kutipan ganda di dalamnya. Baik Anda menggunakan tanda kutip tunggal atau ganda, Anda harus menggunakan pasangan yang cocok untuk membuka dan menutup string nilai atribut. Ada juga urutan escape atau teknik lain yang tersedia untuk mengatasi pembatasan karakter yang diberlakukan oleh sintaks XAML tertentu. Lihat Entitas Karakter XML danXAML .

Agar dapat diatur melalui sintaks atribut, properti harus publik dan harus dapat ditulis. Nilai properti dalam sistem jenis backing harus merupakan jenis nilai, atau harus merupakan jenis referensi yang dapat diinstansiasi atau dirujuk oleh prosesor XAML saat mengakses jenis backing yang relevan.

Untuk peristiwa WPF XAML, peristiwa yang direferensikan sebagai nama atribut harus bersifat publik dan memiliki delegasi publik.

Properti atau acara harus menjadi anggota dari kelas atau struktur yang diinisiasi oleh elemen objek yang memuat.

Pemrosesan Nilai Atribut

Nilai string yang terkandung dalam tanda kutip pembuka dan penutupan diproses oleh prosesor XAML. Untuk properti, perilaku pemrosesan default ditentukan oleh jenis properti CLR yang mendasar.

Nilai atribut diisi oleh salah satu hal berikut, menggunakan urutan pemrosesan ini:

  1. Jika prosesor XAML menemukan kurung kurawal, atau elemen objek yang berasal dari MarkupExtension, maka ekstensi markup yang direferensikan dievaluasi terlebih dahulu daripada memproses nilai sebagai string, dan objek yang dikembalikan oleh ekstensi markup digunakan sebagai nilai. Dalam banyak kasus, objek yang dikembalikan oleh ekstensi markup akan menjadi referensi ke objek yang ada, atau ekspresi yang menunda evaluasi hingga waktu berjalan, dan bukan objek yang baru dibuat.

  2. Jika properti dideklarasikan dengan TypeConverteryang diatribusikan , atau jenis nilai properti tersebut dideklarasikan dengan TypeConverteratribut , nilai string atribut dikirimkan ke pengonversi jenis sebagai input konversi, dan pengonversi akan mengembalikan instans objek baru.

  3. Jika TypeConvertertidak ada, akan dicoba konversi langsung ke jenis properti. Tingkat akhir ini adalah konversi langsung pada nilai yang sesuai sumber parser antara jenis primitif bahasa XAML, atau pemeriksaan terhadap nama-nama konstanta dalam enumerasi (pengurai kemudian mengakses nilai yang cocok).

Nilai Atribut Enumerasi

Enumerasi dalam XAML diproses secara intrinsik oleh pengurai XAML, dan anggota enumerasi harus ditentukan dengan menentukan nama string dari salah satu konstanta bernama enumerasi.

Untuk nilai enumerasi nonflag, perilaku aslinya adalah memproses string nilai atribut dan menyelesaikannya ke salah satu nilai enumerasi. Anda tidak menentukan enumerasi dalam format Enumerasi.Nilai, seperti yang biasa Anda lakukan pada kode. Sebagai gantinya, Anda hanya menentukan Nilai, dan Enumerasi disimpulkan dari jenis properti yang Anda tetapkan. Jika Anda menentukan atribut dalam bentuk Enumerasi. Nilai, atribut tersebut tidak akan diselesaikan dengan benar.

Untuk enumerasi berbasis bendera, perilaku didasarkan pada metode Enum.Parse. Anda dapat menentukan beberapa nilai untuk enumerasi berbendera dengan memisahkan setiap nilai dengan koma. Namun, Anda tidak dapat menggabungkan nilai enumerasi yang tidak berbendera. Misalnya, Anda tidak dapat menggunakan sintaks koma untuk mencoba membuat Trigger yang bertindak pada beberapa kondisi enumerasi nonflag:

<!--This will not compile, because Visibility is not a flagwise enumeration.-->  
...  
<Trigger Property="Visibility" Value="Collapsed,Hidden">  
  <Setter ... />  
</Trigger>  
...  

Enumerasi flagwise yang mendukung atribut yang dapat diatur di XAML jarang terjadi di WPF. Namun, salah satu enumerasi tersebut adalah StyleSimulations. Anda dapat, misalnya, menggunakan sintaks atribut flagwise yang dibatasi koma untuk memodifikasi contoh yang disediakan dalam Keterangan untuk kelas Glyphs; StyleSimulations = "BoldSimulation" bisa menjadi StyleSimulations = "BoldSimulation,ItalicSimulation". KeyBinding.Modifiers adalah properti lain di mana lebih dari satu nilai enumerasi dapat ditentukan. Namun, properti ini adalah kasus khusus, karena enumerasi ModifierKeys mendukung konverter tipe bawaan. Pengonversi jenis untuk pengubah menggunakan tanda plus (+) sebagai pemisah daripada koma (,). Konversi ini mendukung sintaksis yang lebih tradisional untuk mewakili kombinasi kunci dalam pemrograman Microsoft Windows, seperti "Ctrl+Alt".

Properti dan Referensi Nama Anggota Acara

Saat menentukan atribut, Anda dapat mereferensikan properti atau peristiwa apa pun yang ada sebagai anggota jenis CLR yang Anda buat untuk elemen objek yang berisi.

Atau, Anda dapat mereferensikan properti terlampir atau peristiwa terlampir, terlepas dari elemen objek yang berisi. (Properti terlampir dibahas di bagian yang akan datang.)

Anda juga dapat memberi nama peristiwa apa pun dari objek apa pun yang dapat diakses melalui namespace default dengan menggunakan typeName .peristiwa nama yang memenuhi syarat sebagian; sintaks ini mendukung pemasangan handler untuk peristiwa yang dirutekan di mana handler dimaksudkan untuk menangani perutean peristiwa dari elemen turunan, tetapi elemen induk tidak juga memiliki peristiwa tersebut dalam tabel anggotanya. Sintaks ini menyerupai sintaks peristiwa terikat, tetapi peristiwa di sini bukan peristiwa terikat yang sebenarnya. Sebagai gantinya, Anda merujuk peristiwa dengan nama yang memenuhi kualifikasi. Untuk informasi selengkapnya, lihat Gambaran Umum Peristiwa Yang Dirutekan .

Untuk beberapa skenario, nama properti terkadang disediakan sebagai nilai atribut, bukan nama atribut. Nama properti tersebut juga dapat menyertakan kualifikasi, seperti properti yang ditentukan dalam format ownerType.dependencyPropertyName. Skenario ini umum saat menulis gaya atau templat di XAML. Aturan pemrosesan untuk nama properti yang disediakan sebagai nilai atribut berbeda, dan diatur oleh jenis properti yang ditetapkan atau oleh perilaku subsistem WPF tertentu. Untuk detailnya, lihat Styling dan Templating.

Penggunaan lain untuk nama properti adalah ketika nilai atribut menjelaskan hubungan properti-properti. Fitur ini digunakan untuk pengikatan data dan untuk target storyboard, dan diaktifkan oleh kelas PropertyPath dan konverter jenisnya. Untuk deskripsi yang lebih lengkap tentang semantik pencarian, lihat Sintaks PropertyPath XAML.

Sintaks Elemen Properti

sintaks elemen properti ini adalah sintaks yang agak berbeda dari aturan sintaks XML dasar untuk elemen. Dalam XML, nilai atribut adalah string de facto, dengan satu-satunya kemungkinan variasi adalah format pengodean string mana yang digunakan. Di XAML, Anda dapat menetapkan elemen objek lain untuk menjadi nilai properti. Kemampuan ini diaktifkan oleh sintaks elemen properti. Alih-alih properti yang ditentukan sebagai atribut dalam tag elemen, properti ditentukan menggunakan tag elemen pembuka di elementTypeNamedengan formatpropertyName, nilai properti ditentukan di dalamnya, lalu properti tersebut ditutup.

Secara khusus, sintaks dimulai dengan kurung sudut kiri (<), diikuti segera dengan nama jenis kelas atau struktur yang dimuat sintaks elemen properti. Ini diikuti segera dengan titik tunggal (.), kemudian dengan nama properti, kemudian dengan tanda kurung sudut kanan (>). Seperti sintaks atribut, properti tersebut harus ada dalam anggota publik yang dideklarasikan dari jenis yang ditentukan. Nilai yang akan ditetapkan ke properti terkandung dalam elemen properti. Biasanya, nilai diberikan sebagai satu atau beberapa elemen objek, karena menentukan objek sebagai nilai adalah skenario yang dimaksudkan sintaks elemen properti untuk ditangani. Terakhir, tag penutup sepadan yang menentukan elemenTypeName yang sama. kombinasi propertyName harus disediakan, dengan susunan dan keseimbangan yang tepat bersama dengan tag elemen lainnya.

Misalnya, berikut ini adalah sintaks elemen properti untuk properti ContextMenu dari Button.

<Button>
  <Button.ContextMenu>
    <ContextMenu>
      <MenuItem Header="1">First item</MenuItem>
      <MenuItem Header="2">Second item</MenuItem>
    </ContextMenu>
  </Button.ContextMenu>
  Right-click me!</Button>

Nilai dalam elemen properti juga dapat diberikan sebagai teks dalam, dalam kasus di mana jenis properti yang ditentukan adalah jenis nilai primitif, seperti String, atau enumerasi tempat nama ditentukan. Kedua penggunaan ini agak jarang terjadi, karena masing-masing kasus ini juga dapat menggunakan sintaks atribut yang lebih sederhana. Salah satu skenario untuk mengisi elemen properti dengan string adalah untuk properti yang bukan properti konten XAML tetapi masih digunakan untuk representasi teks UI, dan elemen spasi putih tertentu seperti linefeed diperlukan untuk muncul dalam teks UI tersebut. Sintaks atribut tidak dapat mempertahankan linefeed, tetapi sintaks elemen properti dapat, selama pelestarian spasi putih yang signifikan aktif (untuk detailnya, lihat Pemrosesan spasi putih di XAML). Skenario lain adalah agar x:Uid Directive dapat diterapkan ke elemen properti dan dengan demikian menandai nilai dalam sebagai nilai yang harus dilokalkan dalam BAML output WPF atau dengan teknik lain.

Elemen properti tidak diwakili di pohon logis WPF. Elemen properti hanyalah sintaksis tertentu untuk mengatur properti, dan bukan elemen yang memiliki instans atau objek yang mendukungnya. (Untuk detail tentang konsep pohon logis, lihat pohon di WPF.)

Untuk properti di mana sintaks atribut dan elemen properti didukung, dua sintaks umumnya memiliki hasil yang sama, meskipun seluk beluk seperti penanganan spasi putih dapat sedikit bervariasi di antara sintaks.

Sintaks untuk Koleksi

Spesifikasi XAML memerlukan implementasi prosesor XAML untuk mengidentifikasi properti di mana jenis nilai adalah koleksi. Implementasi prosesor XAML umum di .NET didasarkan pada kode terkelola dan CLR, dan mengidentifikasi jenis koleksi melalui salah satu hal berikut:

Jika jenis properti adalah koleksi, maka jenis koleksi yang disimpulkan tidak perlu ditentukan dalam markup sebagai elemen objek. Sebagai gantinya, elemen yang dimaksudkan untuk menjadi item dalam koleksi ditentukan sebagai satu atau beberapa elemen turunan dari elemen properti. Setiap item tersebut dievaluasi menjadi objek selama proses pemuatan dan ditambahkan ke koleksi dengan memanggil metode Add dari koleksi tersirat. Misalnya, properti Triggers dari Style menggunakan tipe koleksi khusus TriggerCollection, yang mengimplementasikan IList. Tidak perlu membuat instans elemen objek TriggerCollection dalam markup. Sebagai gantinya, Anda menentukan satu atau beberapa item Trigger sebagai elemen dalam elemen properti Style.Triggers, di mana Trigger (atau kelas turunan) adalah jenis yang diharapkan sebagai jenis item untuk TriggerCollectionyang sangat diketik dan implisit.

<Style x:Key="SpecialButton" TargetType="{x:Type Button}">
  <Style.Triggers>
    <Trigger Property="Button.IsMouseOver" Value="true">
      <Setter Property = "Background" Value="Red"/>
    </Trigger>
    <Trigger Property="Button.IsPressed" Value="true">
      <Setter Property = "Foreground" Value="Green"/>
    </Trigger>
  </Style.Triggers>
</Style>

Sebuah properti dapat menjadi baik jenis koleksi maupun properti konten XAML untuk jenis tersebut dan jenis-jenis turunan, yang dibahas di bagian berikutnya dari topik ini.

Elemen koleksi implisit membuat anggota di representasi pohon logis, meskipun tidak muncul di markup sebagai elemen. Biasanya konstruktor jenis induk melakukan instansiasi untuk koleksi yang merupakan salah satu propertinya, dan koleksi yang awalnya kosong menjadi bagian dari pohon objek.

Nota

Daftar generik dan antarmuka kamus (IList<T> dan IDictionary<TKey,TValue>) tidak didukung untuk deteksi koleksi. Namun, Anda dapat menggunakan kelas List<T> sebagai kelas dasar, karena menerapkan IList secara langsung, atau Dictionary<TKey,TValue> sebagai kelas dasar, karena menerapkan IDictionary secara langsung.

Di halaman Referensi .NET untuk jenis koleksi, sintaksis ini dengan penghilangan sengaja elemen objek untuk koleksi terkadang dicatat di bagian sintaks XAML sebagai Sintaks Koleksi Implisit.

Dengan pengecualian elemen akar, setiap elemen objek dalam file XAML yang disarangkan sebagai elemen turunan dari elemen lain benar-benar merupakan elemen yang merupakan salah satu atau kedua kasus berikut: anggota properti koleksi implisit dari elemen induknya, atau elemen yang menentukan nilai properti konten XAML untuk elemen induk (properti konten XAML akan dibahas di bagian yang akan datang). Dengan kata lain, hubungan elemen induk dan elemen turunan di halaman markup benar-benar merupakan objek tunggal di akar, dan setiap elemen objek di bawah akar adalah instans tunggal yang menyediakan nilai properti induk, atau salah satu item dalam koleksi yang juga merupakan nilai properti jenis koleksi induk. Konsep akar tunggal ini umum dengan XML, dan sering diperkuat dalam perilaku API yang memuat XAML seperti Load.

Contoh berikut adalah sintaksis dengan elemen objek untuk koleksi (GradientStopCollection) yang ditentukan secara eksplisit.

<LinearGradientBrush>  
  <LinearGradientBrush.GradientStops>  
    <GradientStopCollection>  
      <GradientStop Offset="0.0" Color="Red" />  
      <GradientStop Offset="1.0" Color="Blue" />  
    </GradientStopCollection>  
  </LinearGradientBrush.GradientStops>  
</LinearGradientBrush>  

Perhatikan bahwa tidak selalu mungkin untuk secara eksplisit mendeklarasikan koleksi. Misalnya, mencoba mendeklarasikan TriggerCollection secara eksplisit dalam contoh Triggers yang ditampilkan sebelumnya akan gagal. Secara eksplisit menyatakan koleksi mengharuskan kelas koleksi harus mendukung konstruktor tanpa parameter, dan TriggerCollection tidak memiliki konstruktor tanpa parameter.

Properti Konten XAML

Sintaksis konten XAML adalah sintaks yang hanya diaktifkan pada kelas yang menentukan ContentPropertyAttribute sebagai bagian dari deklarasi kelasnya. ContentPropertyAttribute mereferensikan nama properti yang merupakan properti konten untuk jenis elemen tersebut (termasuk kelas turunan). Ketika diproses oleh prosesor XAML, elemen turunan atau teks dalam apa pun yang ditemukan antara tag pembuka dan penutup elemen objek akan ditetapkan menjadi nilai properti konten XAML untuk objek tersebut. Anda diizinkan untuk menentukan elemen properti eksplisit untuk properti konten, tetapi penggunaan ini umumnya tidak ditampilkan di bagian sintaks XAML dalam referensi .NET. Teknik eksplisit/verbose memiliki nilai tertentu pada keadaan tertentu untuk kejelasan dalam markup atau sebagai bagian dari gaya markup, tetapi biasanya niat properti konten adalah untuk mengoptimalkan markup sehingga elemen yang terkait secara intuitif sebagai induk dan anak dapat disarangkan secara langsung. Tag elemen properti untuk properti lain pada elemen tidak ditetapkan sebagai "konten" per definisi bahasa XAML yang ketat; mereka diproses sebelumnya dalam urutan pemrosesan pengurai XAML dan tidak dianggap sebagai "konten".

Nilai properti konten XAML harus berdampingan

Nilai properti konten XAML harus diberikan sepenuhnya sebelum atau seluruhnya setelah elemen properti lain pada elemen objek tersebut. Ini benar apakah nilai properti konten XAML ditentukan sebagai string, atau sebagai satu atau beberapa objek. Misalnya, markup berikut tidak dapat dianalisis:

<Button>I am a
  <Button.Background>Blue</Button.Background>  
  blue button</Button>  

Ini ilegal pada dasarnya karena jika sintaks ini dibuat eksplisit dengan menggunakan sintaks elemen properti untuk properti konten, maka properti konten akan diatur dua kali:

<Button>  
  <Button.Content>I am a </Button.Content>  
  <Button.Background>Blue</Button.Background>  
  <Button.Content> blue button</Button.Content>  
</Button>  

Contoh ilegal yang sama adalah jika properti konten adalah koleksi, dan elemen turunan diselingi dengan elemen properti:

<StackPanel>  
  <Button>This example</Button>  
  <StackPanel.Resources>  
    <SolidColorBrush x:Key="BlueBrush" Color="Blue"/>  
  </StackPanel.Resources>  
  <Button>... is illegal XAML</Button>  
</StackPanel>  

Properti Konten dan Sintaks Koleksi Digabungkan

Untuk menerima lebih dari satu elemen objek sebagai konten, jenis properti konten harus secara khusus menjadi jenis koleksi. Mirip dengan sintaks elemen properti untuk jenis koleksi, prosesor XAML harus mengidentifikasi jenis yang merupakan jenis koleksi. Jika elemen memiliki properti konten XAML dan jenis properti konten XAML adalah koleksi, maka jenis koleksi tersirat tidak perlu ditentukan dalam markup sebagai elemen objek dan properti konten XAML tidak perlu ditentukan sebagai elemen properti. Oleh karena itu, model konten yang tampak dalam markup kini dapat memiliki lebih dari satu elemen anak yang ditetapkan sebagai konten. Berikut ini adalah sintaks konten untuk kelas turunan Panel. Semua kelas turunan Panel menetapkan properti konten XAML menjadi Children, yang memerlukan nilai jenis UIElementCollection.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  >
  <StackPanel>
    <Button>Button 1</Button>
    <Button>Button 2</Button>
    <Button>Button 3</Button>
  </StackPanel>
</Page>

Perhatikan bahwa elemen properti untuk Children atau elemen untuk UIElementCollection tidak diperlukan dalam markup. Ini adalah fitur desain XAML sehingga elemen yang terkandung secara rekursif yang mendefinisikan UI lebih intuitif diwakili sebagai pohon elemen berlapis dengan hubungan elemen induk-turunan langsung, tanpa mengintervensi tag elemen properti atau objek koleksi. Bahkan, UIElementCollection tidak dapat ditentukan secara eksplisit dalam markup sebagai elemen objek, berdasarkan desain. Karena satu-satunya penggunaan yang dimaksudkan adalah sebagai koleksi implisit, UIElementCollection tidak mengekspos konstruktor tanpa parameter publik dan dengan demikian tidak dapat dibuat sebagai elemen objek.

Mencampur Elemen Properti dan Elemen Objek dalam Objek dengan Properti Isi

Spesifikasi XAML menyatakan bahwa prosesor XAML dapat memberlakukan bahwa elemen objek yang digunakan untuk mengisi properti konten XAML dalam elemen objek harus bersebelahan, dan tidak boleh dicampur. Pembatasan terhadap pencampuran elemen dan konten properti ini diberlakukan oleh prosesor WPF XAML.

Anda dapat memiliki elemen objek turunan sebagai markup langsung pertama dalam elemen objek. Kemudian Anda bisa memperkenalkan elemen-elemen properti. Atau, Anda dapat menentukan satu atau beberapa elemen properti, lalu konten, lalu lebih banyak elemen properti. Tetapi setelah elemen properti mengikuti konten, Anda tidak dapat memperkenalkan konten lebih lanjut, Anda hanya dapat menambahkan elemen properti.

Persyaratan urutan elemen konten/properti ini tidak berlaku untuk teks dalam yang digunakan sebagai konten. Namun, ini masih merupakan gaya markup yang baik untuk menjaga teks dalam tetap berdekatan, karena ruang putih yang signifikan akan sulit dideteksi secara visual dalam markup jika elemen properti diselingi dengan teks dalam.

Namespace XAML

Tidak ada contoh sintaks sebelumnya yang menentukan namespace XAML selain namespace XAML default. Dalam aplikasi WPF umum, namespace XAML default ditetapkan sebagai namespace WPF. Anda dapat menentukan namespace XAML selain namespace XAML default dan masih menggunakan sintaks yang sama. Namun, di mana pun sebuah kelas dinamai yang tidak dapat diakses dalam namespace XAML bawaan, nama kelas tersebut harus didahului dengan awalan namespace XAML sebagaimana dipetakan ke dalam namespace CLR yang sesuai. Misalnya, <custom:Example/> adalah sintaks elemen objek untuk membuat instans kelas Example, di mana namespace CLR yang berisi kelas tersebut (dan mungkin informasi rakitan eksternal yang berisi jenis backing) sebelumnya dipetakan ke awalan custom.

Untuk informasi selengkapnya tentang namespace XAML, lihat Namespace XAML dan Pemetaan Namespace untuk WPF XAML.

Ekstensi Markup

XAML mendefinisikan entitas pemrograman ekstensi markup yang memungkinkan escape dari penanganan prosesor XAML normal dari nilai atribut string atau elemen objek, dan menugaskan pemrosesan ke kelas pendukung. Karakter yang mengidentifikasi ekstensi markup ke prosesor XAML saat menggunakan sintaks atribut adalah kurung kurawal pembuka ({), diikuti oleh karakter apa pun selain kurung kurawal penutup (}). String pertama yang mengikuti kurung kurawal pembuka harus mereferensikan kelas yang menyediakan perilaku ekstensi tertentu, di mana referensi dapat menghilangkan substring "Ekstensi" jika substring tersebut adalah bagian dari nama kelas yang sebenarnya. Setelah itu, satu spasi dapat muncul, dan kemudian setiap karakter berikutnya digunakan oleh implementasi ekstensi sebagai masukan, hingga kurung kurawal penutup ditemukan.

Implementasi .NET XAML menggunakan kelas abstrak MarkupExtension sebagai dasar untuk semua ekstensi markup yang didukung oleh WPF serta kerangka kerja atau teknologi lainnya. Ekstensi markup yang secara khusus diterapkan WPF sering dimaksudkan untuk memberikan sarana untuk mereferensikan objek lain yang ada, atau untuk membuat referensi yang ditangguhkan ke objek yang akan dievaluasi pada waktu proses. Misalnya, pengikatan data WPF sederhana dilakukan dengan menentukan ekstensi markup {Binding} sebagai pengganti nilai yang biasanya akan diambil properti tertentu. Banyak ekstensi markup WPF memungkinkan sintaks atribut untuk properti di mana sebelumnya sintaks atribut tidak mungkin dilakukan. Misalnya, objek Style adalah jenis yang relatif kompleks yang berisi serangkaian objek dan properti berlapis. Gaya dalam WPF biasanya didefinisikan sebagai sumber daya dalam ResourceDictionary, lalu dirujuk melalui salah satu dari dua ekstensi markup WPF yang meminta sumber daya. Ekstensi markup menunda evaluasi nilai properti ke pencarian sumber daya dan memungkinkan pemberian nilai properti Style, dengan tipe Style, dalam sintaks atribut seperti dalam contoh berikut:

<Button Style="{StaticResource MyStyle}">My button</Button>

Di sini, StaticResource mengidentifikasi kelas StaticResourceExtension yang menyediakan implementasi ekstensi markup. String berikutnya MyStyle digunakan sebagai input untuk konstruktor non-default StaticResourceExtension, di mana parameter yang diambil dari string ekstensi mendeklarasikan ResourceKeyyang diminta. diharapkan menjadi nilai x:Key dari yang didefinisikan sebagai sumber daya. Ekstensi Markup StaticResource permintaan penggunaan yang digunakan sumber daya untuk memberikan nilai properti melalui logika pencarian sumber daya statis pada waktu pemuatan.

Untuk informasi selengkapnya tentang ekstensi markup, lihat Ekstensi Markup danWPF XAML . Untuk referensi tentang ekstensi markup dan fitur pemrograman XAML lainnya yang diaktifkan dalam implementasi XAML .NET secara umum, lihat Fitur Bahasa Namespace XAML (x:). Untuk ekstensi markup khusus WPF, lihat Ekstensi WPF XAML.

Properti yang Terlampir

Properti terlampir adalah konsep pemrograman yang diperkenalkan dalam XAML di mana properti dapat dimiliki dan didefinisikan oleh jenis tertentu, tetapi ditetapkan sebagai atribut atau elemen properti pada elemen apa pun. Skenario utama yang ditujukan untuk properti terlampir adalah mengaktifkan elemen turunan dalam struktur markup untuk melaporkan informasi ke elemen induk tanpa memerlukan model objek yang dibagikan secara luas di semua elemen. Sebaliknya, properti terlampir dapat digunakan oleh elemen induk untuk melaporkan informasi ke elemen turunan. Untuk informasi selengkapnya tentang tujuan properti terlampir dan cara membuat properti terlampir Anda sendiri, lihat Gambaran Umum Properti Terlampir .

Properti terlampir menggunakan sintaksis yang secara dangkal menyerupai sintaks elemen properti, karena Anda juga menentukan kombinasi typeName.propertyName. Ada dua perbedaan penting:

  • Anda dapat menggunakan kombinasi typeName , propertyName, dan bahkan saat mengatur properti terlampir melalui sintaks atribut. Properti terlampir adalah satu-satunya kasus di mana menggunakan nama properti secara lengkap adalah persyaratan dalam sintaks atribut.

  • Anda juga dapat menggunakan sintaks elemen properti untuk properti terlampir. Namun, untuk sintaks elemen properti umum, typeName Anda tentukan adalah elemen objek yang berisi elemen properti. Jika Anda merujuk ke properti terlampir, maka typeName adalah kelas yang menentukan properti terlampir, bukan elemen objek yang berisi.

Kejadian Terlampir

Peristiwa terlampir adalah konsep pemrograman lain yang diperkenalkan di XAML di mana peristiwa dapat didefinisikan oleh jenis tertentu, tetapi handler dapat dilampirkan pada elemen objek apa pun. Dalam implementasi WOF, seringkali jenis yang mendefinisikan peristiwa terlampir adalah jenis statis yang mendefinisikan layanan, dan terkadang peristiwa terlampir tersebut diekspos oleh alias peristiwa yang dirutekan dalam jenis yang mengekspos layanan. Handler untuk event yang dilampirkan ditentukan melalui sintaksis atribut. Seperti halnya peristiwa terlampir, sintaks untuk atribut diperluas dalam peristiwa terlampir untuk memungkinkan penggunaan tipe NamaTipe.NamaPeristiwa, di mana NamaTipe adalah kelas yang menyediakan aksesor penanganan peristiwa Add dan Remove untuk infrastruktur peristiwa terlampir, dan NamaPeristiwa adalah nama peristiwa tersebut.

Anatomi Elemen Induk XAML

Tabel berikut menunjukkan elemen akar XAML umum yang dipecah, memperlihatkan atribut tertentu dari elemen akar:

Atribut Deskripsi
<Page Membuka elemen objek dari elemen akar
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Namespace XAML bawaan (WPF)
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Namespace XAML untuk bahasa XAML
x:Class="ExampleNamespace.ExampleCode" Deklarasi kelas parsial yang menghubungkan markup dengan kode-belakang apa pun yang ditetapkan untuk kelas parsial tersebut
> Akhir elemen objek untuk akar. Objek belum ditutup karena elemen berisi elemen turunan

Penggunaan XAML Opsional dan Tidak Direkomendasikan

Bagian berikut menjelaskan penggunaan XAML yang secara teknis didukung oleh prosesor XAML, tetapi itu menghasilkan verbositas atau masalah estetika lainnya yang mengganggu file XAML yang tetap dapat dibaca manusia saat Anda mengembangkan aplikasi yang berisi sumber XAML.

Penggunaan Elemen Properti Opsional

Penggunaan elemen properti opsional termasuk menulis properti konten elemen secara eksplisit yang dianggap implisit oleh prosesor XAML. Misalnya, ketika Anda mendeklarasikan konten Menu, Anda dapat memilih untuk secara eksplisit mendeklarasikan koleksi ItemsMenu sebagai tag elemen properti <Menu.Items>, dan menempatkan setiap MenuItem dalam <Menu.Items>, daripada menggunakan perilaku prosesor XAML implisit bahwa semua elemen anak dari Menu harus menjadi MenuItem dan ditempatkan dalam koleksi Items. Terkadang penggunaan opsional dapat membantu memperjelas struktur objek secara visual seperti yang diwakili dalam markup. Atau terkadang penggunaan elemen properti eksplisit dapat menghindari markup yang secara teknis berfungsi tetapi membingungkan secara visual, seperti ekstensi markup berlapis dalam nilai atribut.

Atribut Lengkap yang Memenuhi Kualifikasi dari typeName.memberName

typeName .bentuk memberName untuk atribut sebenarnya berfungsi lebih serbaguna daripada hanya kasus peristiwa yang dirutekan. Tetapi dalam situasi lain, bentuk itu berlebihan dan Anda harus menghindarinya, bahkan jika hanya untuk alasan gaya markup dan keterbacaan. Dalam contoh berikut, masing-masing dari tiga referensi ke atribut Background benar-benar setara:

<Button Background="Blue">Background</Button>
<Button Button.Background="Blue">Button.Background</Button>
<Button Control.Background="Blue">Control.Background</Button>

Button.Background berfungsi karena pencarian yang memenuhi syarat untuk properti tersebut pada Button berhasil (Background diwarisi dari Kontrol) dan Button adalah kelas elemen objek atau kelas dasar. Control.Background berfungsi karena kelas Control benar-benar mendefinisikan Background dan Control adalah kelas dasar Button.

Namun, typeName berikut.contoh formulir memberName tidak berfungsi sehingga ditampilkan dalam bentuk komentar.

<!--<Button Label.Background="Blue">Does not work</Button> -->

Label adalah kelas turunan lain dari Control, dan jika Anda telah menentukan Label.Background dalam elemen objek Label, penggunaan ini akan berfungsi. Namun, karena Label bukan kelas atau kelas dasar Button, perilaku prosesor XAML yang ditentukan adalah memproses Label.Background sebagai properti terlampir. Label.Background bukan properti terlampir yang tersedia, dan penggunaan ini gagal.

Elemen Properti dari baseTypeName.memberName

Dengan cara yang mirip dengan bagaimana typeName.cara kerja memberName berfungsi untuk sintaks atribut, sintaks baseTypeName.memberName berfungsi untuk sintaks elemen properti. Misalnya, sintaks berikut berfungsi:

<Button>Control.Background PE
  <Control.Background>
    <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
      <GradientStop Color="Yellow" Offset="0.0" />
      <GradientStop Color="LimeGreen" Offset="1.0" />
    </LinearGradientBrush>
    </Control.Background>
</Button>

Di sini, elemen properti diberikan sebagai Control.Background meskipun elemen properti terkandung dalam Button.

Tapi sama seperti typeName.formulir memberName untuk atribut, baseTypeName. memberName adalah gaya yang buruk dalam markup, dan Anda harus menghindarinya.

Lihat juga