Gambaran Umum XAML (WPF .NET)

Artikel ini menjelaskan fitur bahasa XAML dan menunjukkan bagaimana Anda dapat menggunakan XAML untuk membuat aplikasi Windows Presentation Foundation (WPF). Artikel ini secara khusus menjelaskan XAML seperti yang diterapkan oleh WPF. XAML sendiri adalah konsep bahasa yang lebih besar dari WPF.

Penting

Dokumentasi Panduan Desktop untuk .NET 7 dan .NET 6 sedang dibangun.

Apa itu XAML

XAML adalah bahasa markup deklaratif. Seperti yang diterapkan pada model pemrograman .NET, XAML menyederhanakan pembuatan UI untuk aplikasi .NET. Anda dapat membuat elemen UI yang terlihat di markup XAML deklaratif, lalu memisahkan definisi UI dari logika runtime dengan menggunakan file code-behind yang digabungkan ke markup melalui definisi kelas parsial. XAML secara langsung mewakili instantiasi objek dalam satu set jenis dukungan tertentu yang ditentukan dalam rakitan. Ini tidak seperti kebanyakan bahasa markup lainnya, yang biasanya merupakan bahasa yang ditafsirkan tanpa ikatan langsung ke sistem jenis pendukung. XAML memungkinkan alur kerja tempat pihak yang terpisah dapat bekerja pada UI dan logika aplikasi, menggunakan alat yang berpotensi berbeda.

Jika direpresentasikan sebagai teks, file XAML adalah file XML yang umumnya memiliki ekstensi .xaml. File dapat dikodekan oleh pengodean XML apa pun, tetapi pengodean sebagai UTF-8 sudah umum.

Contoh berikut menunjukkan bagaimana Anda dapat membuat tombol sebagai bagian dari UI. Contoh ini ditujukan untuk memberi Anda gambaran tentang bagaimana XAML merepresentasikan metafora pemrograman UI umum (ini bukan sampel lengkap).

<StackPanel>
    <Button Content="Click Me"/>
</StackPanel>

Sintaksis XAML secara singkat

Bagian berikut menjelaskan bentuk dasar sintaksis XAML, dan memberikan contoh markup singkat. Bagian ini tidak ditujukan untuk memberikan informasi lengkap tentang setiap bentuk sintaksis, seperti bagaimana ini direpresentasikan dalam sistem jenis dukungan. Untuk informasi lebih lanjut tentang spesifikasi sintaksis XAML, lihat Detail Sintaksis XAML.

Sebagian besar materi di beberapa bagian berikutnya akan menjadi dasar bagi Anda jika sebelumnya sudah terbiasa dengan bahasa XML. Ini adalah konsekuensi dari salah satu prinsip desain dasar XAML. Bahasa XAML mendefinisikan konsepnya sendiri, tetapi konsep ini bekerja dalam bahasa XML dan bentuk markup.

Elemen objek XAML

Elemen objek biasanya mendeklarasikan turunan dari suatu jenis. Jenis tersebut didefinisikan dalam rakitan yang direferensikan oleh teknologi yang menggunakan XAML sebagai bahasa.

Sintaksis elemen objek selalu dimulai dengan kurung sudut pembuka (<). Kemudian diikuti dengan nama jenis tempat Anda ingin membuat instans. (Nama dapat menyertakan awalan, konsep yang akan dijelaskan nanti.) Setelah ini, Anda dapat mendeklarasikan atribut secara opsional pada elemen objek. Untuk melengkapi tag elemen objek, akhiri dengan kurung siku penutup (>). Anda dapat menggunakan formulir penutupan sendiri yang tidak memiliki konten apa pun, dengan melengkapi tag dengan garis miring ke depan dan tanda kurung sudut penutup secara berurutan (/>). Misalnya, lihat kembali cuplikan kode markup yang ditampilkan sebelumnya.

<StackPanel>
    <Button Content="Click Me"/>
</StackPanel>

Hal ini menentukan dua elemen objek: <StackPanel> (dengan konten, dan tag penutup nanti), dan <Button .../> (formulir menutup sendiri, dengan beberapa atribut). Elemen objek StackPanel dan Button masing-masing memetakan ke nama kelas yang didefinisikan oleh WPF dan merupakan bagian dari rakitan WPF. Saat menentukan tag elemen objek, Anda membuat instruksi untuk pemrosesan XAML untuk membuat instans baru dari jenis yang mendasarinya. Setiap instans dibuat dengan memanggil konstruktor tanpa parameter dari jenis yang mendasarinya saat mengurai dan memuat XAML.

Sintaksis atribut (properti)

Properti suatu objek sering dapat dinyatakan sebagai atribut dari elemen objek. Sintaksis atribut menamai properti objek yang sedang diatur, diikuti oleh operator penugasan (=). Nilai atribut selalu ditentukan sebagai string yang terdapat dalam tanda kutip.

Sintaksis atribut adalah sintaksis pengaturan properti yang paling efisien dan merupakan sintaksis yang paling intuitif untuk digunakan bagi pengembang yang pernah menggunakan bahasa markup di masa lalu. Misalnya, markup berikut membuat tombol yang memiliki teks merah dan latar belakang biru dengan teks tampilan Content.

<Button Background="Blue" Foreground="Red" Content="This is a button"/>

Sintaksis elemen properti

Untuk beberapa properti elemen objek, sintaksis atribut tidak dimungkinkan, karena objek atau informasi yang diperlukan untuk memberikan nilai properti tidak dapat diekspresikan secara memadai dalam tanda kutip dan batasan string sintaksis atribut. Untuk kasus ini, sintaksis berbeda yang dikenal sebagai sintaksis elemen properti dapat digunakan.

Sintaksis untuk tag awal elemen properti adalah <TypeName.PropertyName>. Umumnya, konten tag tersebut adalah elemen objek dari jenis yang diambil properti sebagai nilainya. Setelah menentukan konten, Anda harus menutup elemen properti dengan tag akhir. Sintaksis untuk tag akhir adalah </TypeName.PropertyName>.

Jika sintaksis atribut memungkinkan, menggunakan sintaksis atribut biasanya lebih nyaman dan memungkinkan markup yang lebih ringkas, tetapi hal ini sering kali hanya masalah gaya, bukan batasan teknis. Contoh berikut menunjukkan properti yang sama yang diatur seperti pada contoh sintaksis atribut sebelumnya, tetapi kali ini dengan menggunakan sintaksis elemen properti untuk semua properti Button.

<Button>
    <Button.Background>
        <SolidColorBrush Color="Blue"/>
    </Button.Background>
    <Button.Foreground>
        <SolidColorBrush Color="Red"/>
    </Button.Foreground>
    <Button.Content>
        This is a button
    </Button.Content>
</Button>

Sintaksis kumpulan

Bahasa XAML mencakup beberapa pengoptimalan yang menghasilkan markup yang lebih dapat dibaca manusia. Salah satu pengoptimalan tersebut adalah bahwa jika properti tertentu mengambil jenis kumpulan, maka item yang Anda nyatakan dalam markup sebagai elemen turunan dalam nilai properti tersebut menjadi bagian dari kumpulan. Dalam hal ini, kumpulan elemen objek turunan adalah nilai yang diatur ke properti kumpulan.

Contoh berikut menunjukkan sintaksis kumpulan untuk mengatur nilai properti GradientStops.

<LinearGradientBrush>
    <LinearGradientBrush.GradientStops>
        <!-- no explicit new GradientStopCollection, parser knows how to find or create -->
        <GradientStop Offset="0.0" Color="Red" />
        <GradientStop Offset="1.0" Color="Blue" />
    </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

Properti konten XAML

XAML menetapkan fitur bahasa ketika suatu kelas dapat menunjuk tepat salah satu propertinya menjadi properti konten XAML. Elemen turunan dari elemen objek tersebut digunakan untuk menetapkan nilai properti konten tersebut. Dengan kata lain, untuk properti konten secara unik, Anda dapat menghilangkan elemen properti saat mengatur properti tersebut di markup XAML dan menghasilkan metafora induk/turunan yang lebih terlihat di markup.

Misalnya, Border menetapkan properti konten dari Child. Dua elemen Border berikut diperlakukan secara identik. Yang pertama memanfaatkan sintaksis properti konten dan menghilangkan elemen properti Border.Child. Yang kedua menunjukkan Border.Child secara eksplisit.

<Border>
    <TextBox Width="300"/>
</Border>
<!--explicit equivalent-->
<Border>
    <Border.Child>
        <TextBox Width="300"/>
    </Border.Child>
</Border>

Sebagai aturan bahasa XAML, nilai properti konten XAML harus diberikan seluruhnya sebelum atau seluruhnya setelah elemen properti lain pada elemen objek tersebut. Misalnya, markup berikut tidak dapat dikompilasi.

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

Untuk informasi lebih lanjut tentang spesifikasi sintaksis XAML, lihat Detail Sintaksis XAML.

Konten teks

Sejumlah kecil elemen XAML dapat langsung memproses teks sebagai kontennya. Untuk mengaktifkannya, salah satu kasus berikut harus benar:

  • Kelas harus mendeklarasikan properti konten, dan properti konten tersebut harus memiliki jenis yang dapat ditetapkan ke string (jenisnya bisa jadi Object). Misalnya, setiap ContentControl menggunakan Content sebagai properti kontennya dan jenisnya Object, dan ini mendukung penggunaan berikut pada ContentControl seperti Button: <Button>Hello</Button>.

  • Jenis harus mendeklarasikan konverter jenis, dalam hal ini konten teks digunakan sebagai teks inisialisasi untuk konverter jenis tersebut. Misalnya, <Brush>Blue</Brush> mengonversi nilai konten Blue menjadi kuas. Kasus ini kurang umum dalam praktik.

  • Jenisnya harus primitif bahasa XAML yang dikenal.

Properti konten dan sintaksis kumpulan digabungkan

Pertimbangkan contoh ini.

<StackPanel>
    <Button>First Button</Button>
    <Button>Second Button</Button>
</StackPanel>

Di sini, setiap Button adalah elemen turunan dari StackPanel. Ini adalah markup yang efisien dan intuitif yang menghilangkan dua tag karena dua alasan berbeda.

  • Elemen properti StackPanel.Children dihilangkan:StackPanel berasal dari Panel. Panel mendefinisikan Panel.Children sebagai properti konten XAML-nya.

  • Elemen objek UIElementCollection dihilangkan: Properti Panel.Children mengambil jenis UIElementCollection, yang menerapkan IList. Tag elemen kumpulan dapat dihilangkan, berdasarkan aturan XAML untuk memproses kumpulan seperti IList. (Dalam hal ini, UIElementCollection sebenarnya tidak dapat dipakai karena tidak mengekspos konstruktor tanpa parameter, dan itulah sebabnya elemen objek UIElementCollection ditampilkan dikomentari).

<StackPanel>
    <StackPanel.Children>
        <!--<UIElementCollection>-->
        <Button>First Button</Button>
        <Button>Second Button</Button>
        <!--</UIElementCollection>-->
    </StackPanel.Children>
</StackPanel>

Sintaksis atribut (peristiwa)

Sintaksis atribut juga dapat digunakan untuk anggota yang merupakan peristiwa, bukan properti. Dalam hal ini, nama atribut adalah nama peristiwa. Dalam penerapan peristiwa WPF untuk XAML, nilai atribut adalah nama penangan yang menerapkan delegasi peristiwa tersebut. Misalnya, markup berikut menetapkan penangan untuk peristiwa Click ke Button yang dibuat di markup:

<Button Click="Button_Click" >Click Me!</Button>

Ada lebih banyak peristiwa dan XAML di WPF jika dibandingkan dengan contoh sintaksis atribut ini saja. Misalnya, Anda mungkin bertanya-tanya apa yang diwakili oleh ClickHandler yang direferensikan di sini dan bagaimana definisinya. Hal ini akan dijelaskan di bagian Peristiwa dan kode XAML di belakang nanti di artikel ini.

Huruf besar kecil dan spasi di XAML

Secara umum, XAML peka terhadap huruf besar/kecil. Untuk tujuan menyelesaikan jenis pendukung, WPF XAML peka huruf besar/kecil dengan aturan yang sama dengan CLR peka huruf besar/kecil. Elemen objek, elemen properti, dan nama atribut semuanya harus ditentukan dengan menggunakan huruf besar/kecil jika dibandingkan dengan nama dengan jenis yang mendasarinya dalam perakitan, atau dengan anggota jenis. Kata kunci dan primitif bahasa XAML juga peka huruf besar/kecil. Nilai tidak selalu peka huruf besar/kecil. Kepekaan huruf besar/kecil untuk nilai akan bergantung pada perilaku konverter jenis yang terkait dengan properti yang mengambil nilai, atau jenis nilai properti. Misalnya, properti yang menggunakan jenis Boolean dapat menggunakan true atau True sebagai nilai yang setara, tetapi hanya karena konversi jenis pengurai WPF XAML native untuk string ke Boolean sudah mengizinkannya sebagai setara.

Prosesor dan pembuat serial WPF XAML akan mengabaikan atau menghapus semua white space yang tidak signifikan, dan akan menormalkan white space yang signifikan. Hal ini konsisten dengan rekomendasi perilaku white space default dari spesifikasi XAML. Perilaku ini hanya konsekuensi ketika Anda menentukan string dalam properti konten XAML. Dalam istilah yang paling sederhana, XAML mengubah spasi, umpan baris, dan karakter tab menjadi spasi, dan kemudian mempertahankan satu spasi jika ditemukan di kedua ujung string yang berdekatan. Penjelasan lengkap tentang penanganan white space XAML tidak dibahas dalam artikel ini. Untuk informasi lebih lanjut, lihat Pemrosesan white space di XAML.

Ekstensi markup

Ekstensi markup adalah konsep bahasa XAML. Saat digunakan untuk memberikan nilai sintaksis atribut, kurung kurawal ({ dan }) menunjukkan penggunaan ekstensi markup. Penggunaan ini mengarahkan pemrosesan XAML untuk melepaskan diri dari perlakuan umum nilai atribut sebagai string literal atau nilai konversi string.

Ekstensi markup yang paling umum digunakan dalam pemrograman aplikasi WPF adalah Binding, digunakan untuk ekspresi pengikatan data, dan referensi sumber daya StaticResource dan DynamicResource. Dengan menggunakan ekstensi markup, Anda dapat menggunakan sintaksis atribut untuk memberikan nilai properti meskipun properti tersebut tidak mendukung sintaksis atribut secara umum. Ekstensi markup sering menggunakan jenis ekspresi perantara untuk mengaktifkan fitur seperti menunda nilai atau mereferensikan objek lain yang hanya ada saat runtime.

Misalnya, markup berikut mengatur nilai properti Style menggunakan sintaksis atribut. Properti Style mengambil turunan dari kelas Style, yang secara default tidak dapat dibuat dengan string sintaksis atribut. Namun dalam kasus ini, atribut tersebut mengacu pada ekstensi markup tertentu, StaticResource. Saat ekstensi markup tersebut diproses, ekstensi tersebut mengembalikan referensi ke gaya yang sebelumnya dipakai sebagai sumber daya yang dikunci dalam kamus sumber daya.

<Window x:Class="index.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="100" Width="300">
    <Window.Resources>
        <SolidColorBrush x:Key="MyBrush" Color="Gold"/>
        <Style TargetType="Border" x:Key="PageBackground">
            <Setter Property="BorderBrush" Value="Blue"/>
            <Setter Property="BorderThickness" Value="5" />
        </Style>
    </Window.Resources>
    <Border Style="{StaticResource PageBackground}">
        <StackPanel>
            <TextBlock Text="Hello" />
        </StackPanel>
    </Border>
</Window>

Untuk daftar referensi semua ekstensi markup untuk XAML yang diterapkan secara khusus di WPF, lihat Ekstensi XAML WPF. Untuk daftar referensi ekstensi markup yang ditentukan oleh System.Xaml dan lebih banyak tersedia untuk implementasi .NET XAML, lihat Fitur Bahasa XAML Namespace (x:). Untuk informasi lebih lanjut tentang konsep ekstensi markup, lihat Ekstensi Markup dan WPF XAML.

Jenis konverter

Pada bagian Sintaksis XAML secara singkat disebutkan bahwa nilai atribut harus dapat diatur oleh string. Penanganan native dan dasar tentang bagaimana string diubah menjadi jenis objek lain atau nilai primitif didasarkan pada jenis String itu sendiri, bersama dengan pemrosesan native untuk jenis tertentu seperti DateTime atau Uri. Tetapi banyak jenis WPF atau anggota dari jenis tersebut memperluas perilaku pemrosesan atribut string dasar sedemikian rupa sehingga contoh jenis objek yang lebih kompleks dapat ditentukan sebagai string dan atribut.

Struktur Thickness adalah contoh jenis yang memiliki konversi jenis yang diaktifkan untuk penggunaan XAML. Thickness menunjukkan pengukuran dalam persegi panjang berlapis dan digunakan sebagai nilai untuk properti seperti Margin. Dengan menempatkan konverter jenis pada Thickness, semua properti yang menggunakan Thickness lebih mudah ditentukan dalam XAML karena dapat ditetapkan sebagai atribut. Contoh berikut menggunakan konversi jenis dan sintaksis atribut untuk memberikan nilai Margin:

<Button Margin="10,20,10,30" Content="Click me"/>

Contoh sintaksis atribut sebelumnya setara dengan contoh sintaksis yang lebih verbose berikut, di mana Margin malah diatur melalui sintaksis elemen properti yang berisi elemen objek Thickness. Empat properti utama Thickness ditetapkan sebagai atribut pada instans baru:

<Button Content="Click me">
    <Button.Margin>
        <Thickness Left="10" Top="20" Right="10" Bottom="30"/>
    </Button.Margin>
</Button>

Catatan

Ada juga objek dalam jumlah terbatas di mana konversi jenis adalah satu-satunya cara umum untuk mengatur properti ke jenis tersebut tanpa melibatkan subkelas, karena jenis tersebut sendiri tidak memiliki konstruktor tanpa parameter. Contohnya Cursor.

Untuk informasi lebih lanjut tentang konversi jenis, lihat TypeConverters dan XAML.

Elemen akar dan namespace

File XAML hanya boleh memiliki satu elemen akar, untuk menjadi file XML yang dibentuk dengan baik dan file XAML yang valid. Untuk skenario WPF biasa, Anda menggunakan elemen akar yang memiliki arti menonjol dalam model aplikasi WPF (misalnya, Window atau Page untuk halaman, ResourceDictionary untuk kamus eksternal, atau Application untuk definisi aplikasi). Contoh berikut menunjukkan elemen akar dari file XAML tipikal untuk halaman WPF, dengan elemen akar Page.

<Page x:Class="index.Page1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Title="Page1">

</Page>

Elemen akar juga berisi atribut xmlns dan xmlns:x. Atribut ini menunjukkan ke prosesor XAML namespace XAML mana yang berisi definisi jenis untuk jenis pendukung yang akan direferensikan markup sebagai elemen. Atribut xmlns secara khusus menunjukkan namespace XAML default. Dalam namespace XAML default, elemen objek dalam markup dapat ditentukan tanpa awalan. Untuk sebagian besar skenario aplikasi WPF, dan untuk hampir semua contoh yang diberikan di bagian WPF SDK, namespace XAML default dipetakan ke namespace WPF http://schemas.microsoft.com/winfx/2006/xaml/presentation. Atribut xmlns:x menunjukkan namespace XAML tambahan, yang memetakan namespace bahasa XAML http://schemas.microsoft.com/winfx/2006/xaml.

Penggunaan xmlns untuk menentukan cakupan penggunaan dan pemetaan namescope konsisten dengan spesifikasi XML 1.0. Namescope XAML berbeda dari namescope XML hanya karena namescope XAML juga menyiratkan sesuatu tentang bagaimana elemen namescope didukung oleh jenis ketika menyangkut resolusi jenis dan mengurai XAML.

Atribut xmlns hanya benar-benar diperlukan pada elemen akar dari setiap file XAML. Definisi xmlns akan berlaku untuk semua elemen turunan dari elemen akar (perilaku ini sekali lagi konsisten dengan spesifikasi XML 1.0 untuk xmlns.) Atribut xmlns juga diizinkan pada elemen lain di bawah akar, dan akan berlaku untuk semua elemen turunan dari elemen penentu. Namun, seringnya definisi atau pendefinisian ulang namespace XAML dapat mengakibatkan gaya markup XAML yang sulit dibaca.

Penerapan WPF dari prosesor XAML-nya mencakup infrastruktur yang memiliki kesadaran akan rakitan inti WPF. Rakitan inti WPF diketahui berisi jenis yang mendukung pemetaan WPF ke namespace XAML default. Hal ini diaktifkan melalui konfigurasi yang merupakan bagian dari file pembangunan proyek Anda dan sistem pembangunan dan proyek WPF. Oleh karena itu, mendeklarasikan namespace XAML default sebagai xmlns default adalah semua yang diperlukan untuk mereferensikan elemen XAML yang berasal dari rakitan WPF.

x: awalan

Dalam contoh elemen akar sebelumnya, awalan x: digunakan untuk memetakan namespace XAML http://schemas.microsoft.com/winfx/2006/xaml, yang merupakan namespace XAML khusus yang mendukung konstruksi bahasa XAML. x: ini digunakan untuk memetakan namespace XAML ini dalam template untuk proyek, dalam contoh, dan dalam dokumentasi di seluruh SDK ini. Namespace XAML untuk bahasa XAML berisi beberapa konstruksi pemrograman yang akan sering Anda gunakan di XAML Anda. Berikut ini adalah daftar konstruksi pemrograman awalan x: paling umum yang akan Anda gunakan:

  • x:Key: Menetapkan kunci unik untuk setiap sumber daya dalam ResourceDictionary (atau konsep kamus serupa di kerangka kerja lain). x:Key mungkin akan mencakup 90 persen dari x: penggunaan yang akan Anda lihat di markup aplikasi WPF biasa.

  • x:Class: Menentukan namespace CLR dan nama kelas untuk kelas yang menyediakan code-behind untuk halaman XAML. Anda harus memiliki kelas seperti itu untuk mendukung code-behind per model pemrograman WPF, dan karena itu Anda hampir selalu melihat x: dipetakan, bahkan jika tidak ada sumber daya.

  • x:Name: Menentukan nama objek runtime untuk instans yang ada dalam kode runtime setelah elemen objek diproses. Secara umum, Anda akan sering menggunakan properti setara yang ditentukan WPF untuk x:Name. Properti tersebut dipetakan secara khusus ke properti pendukung CLR dan karenanya lebih nyaman untuk pemrograman aplikasi, di mana Anda sering menggunakan kode runtime untuk menemukan elemen bernama dari XAML yang diinisialisasi. Properti semacam itu yang paling umum adalah FrameworkElement.Name. Anda mungkin masih menggunakan x:Name jika properti Name tingkat kerangka kerja WPF yang setara tidak didukung dalam jenis tertentu. Ini terjadi dalam skenario animasi tertentu.

  • x:Static: Mengaktifkan referensi yang mengembalikan nilai statis yang bukan merupakan properti yang kompatibel dengan XAML.

  • x:Type: Membuat referensi Type berdasarkan nama jenis. Properti ini digunakan untuk menentukan atribut yang menggunakan Type, seperti Style.TargetType, meskipun seringkali properti memiliki konversi string-to- Type native sedemikian rupa sehingga ekstensi markup x:Type yang digunakan bersifat opsional.

Ada konstruksi pemrograman tambahan di namespace awalan/XAML x:, yang tidak umum. Untuk detailnya, lihat XAML Namespace (x:) Fitur Bahasa.

Awalan khusus dan jenis khusus

Untuk rakitan kustom Anda sendiri, atau untuk rakitan di luar inti WPF dari PresentationCore, PresentationFramework dan WindowsBase, Anda dapat menentukan rakitan sebagai bagian dari pemetaan xmlns kustom. Anda kemudian dapat mereferensikan jenis dari rakitan tersebut di XAML, selama jenis itu diterapkan dengan benar untuk mendukung penggunaan XAML yang Anda coba.

Berikut ini adalah contoh dasar tentang cara kerja awalan kustom di markup XAML. Awalan custom didefinisikan dalam tag elemen akar, dan dipetakan ke rakitan tertentu yang dikemas dan tersedia dengan aplikasi. Rakitan ini berisi jenis NumericUpDown, yang diterapkan untuk mendukung penggunaan XAML umum serta menggunakan pewarisan kelas yang memungkinkan penyisipannya pada titik tertentu ini dalam model konten XAML WPF. Instans dari kontrol NumericUpDown ini dideklarasikan sebagai elemen objek, menggunakan awalan sehingga pengurai XAML mengetahui namespace XAML mana yang berisi jenis, dan oleh karena itu di mana rakitan pendukung yang berisi definisi jenis.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:custom="clr-namespace:NumericUpDownCustomControl;assembly=CustomLibrary"
    >
  <StackPanel Name="LayoutRoot">
    <custom:NumericUpDown Name="numericCtrl1" Width="100" Height="60"/>
...
  </StackPanel>
</Page>

Untuk informasi lebih lanjut tentang jenis khusus dalam XAML, lihat XAML dan Kelas Khusus untuk WPF.

Untuk informasi lebih lanjut tentang bagaimana namespace XML dan namespace kode dalam rakitan terkait, lihat Namespace XAML dan Pemetaan Namespace untuk WPF XAML.

Peristiwa dan kode XAML di belakang

Sebagian besar aplikasi WPF terdiri dari markup XAML dan code-behind. Dalam sebuah proyek, XAML ditulis sebagai file .xaml, dan bahasa CLR seperti Microsoft Visual Basic atau C# digunakan untuk menulis file code-behind. Ketika file XAML dikompilasi markup sebagai bagian dari pemrograman WPF dan model aplikasi, lokasi file code-behind XAML untuk file XAML diidentifikasi dengan menetapkan namespace dan kelas sebagai atribut x:Class dari elemen akar dari XAML.

Dalam contoh sejauh ini, Anda telah melihat beberapa tombol, tetapi tidak satu pun dari tombol ini memiliki perilaku logis yang terkait dengannya. Mekanisme tingkat aplikasi utama untuk menambahkan perilaku untuk elemen objek adalah dengan menggunakan peristiwa yang ada dari kelas elemen, dan untuk menulis penangan khusus untuk peristiwa itu yang dipanggil saat peristiwa tersebut dimunculkan saat runtime. Nama peristiwa dan nama penangan yang akan digunakan ditentukan dalam markup, sedangkan kode yang menerapkan penangan Anda didefinisikan code-behind.

<Page x:Class="ExampleNamespace.ExamplePage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel>
        <Button Click="Button_Click">Click me</Button>
    </StackPanel>
</Page>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace ExampleNamespace;

public partial class ExamplePage : Page
{
    public ExamplePage() =>
        InitializeComponent();

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var buttonControl = (Button)e.Source;
        buttonControl.Foreground = Brushes.Red;
    }
}
Class ExamplePage
    Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
        Dim buttonControl = DirectCast(e.Source, Button)
        buttonControl.Foreground = Brushes.Red
    End Sub
End Class

Perhatikan bahwa file code-behind menggunakan namespace ExampleNamespace CLR (namespace tidak terlihat di Visual Basic) dan menyatakan ExamplePage sebagai kelas parsial dalam namespace tersebut. Hal ini sejajar dengan nilai atribut x:Class dari ExampleNamespace.ExamplePage yang disediakan di akar markup. Pengompilasi markup WPF akan membuat kelas parsial untuk setiap file XAML yang dikompilasi, dengan menurunkan kelas dari jenis elemen akar. Saat memberikan code-behind yang juga mendefinisikan kelas parsial yang sama, kode yang dihasilkan digabungkan dalam namespace dan kelas yang sama dari aplikasi yang dikompilasi.

Penting

Di Visual Basic, namespace layanan akar tersirat untuk XAML dan code-behind. Hanya namespace berlapis yang terlihat. Artikel ini menunjukkan XAML proyek C#.

Untuk informasi lebih lanjut tentang persyaratan untuk pemrograman code-behind di WPF, lihat Persyaratan code-behind, Penanganan Aktivitas, dan Kelas Parsial di WPF.

Jika tidak ingin membuat file code-behind yang terpisah, Anda juga dapat memasukkan kode Anda ke dalam file XAML. Namun, kode inline adalah teknik yang kurang serbaguna yang memiliki keterbatasan substansial. Untuk informasi lebih lanjut, lihat Kode di Belakang dan XAML di WPF.

Peristiwa yang dirutekan

Fitur peristiwa tertentu yang mendasar bagi WPF adalah peristiwa yang dirutekan. Peristiwa yang dirutekan memungkinkan suatu elemen menangani suatu peristiwa yang dimunculkan oleh elemen yang berbeda, selama elemen-elemen tersebut terhubung melalui hubungan pohon. Saat menentukan penanganan peristiwa dengan atribut XAML, peristiwa yang dirutekan dapat didengarkan dan ditangani pada elemen apa pun, termasuk elemen yang tidak mencantumkan peristiwa tertentu dalam tabel anggota kelas. Hal ini dicapai dengan mengkualifikasikan atribut nama peristiwa dengan nama kelas pemilik. Misalnya, induk StackPanel dalam contoh StackPanel / Button yang sedang berlangsung dapat mendaftarkan penangan untuk peristiwa Click tombol elemen turunan dengan menetapkan atribut Button.Click pada elemen objek StackPanel, dengan nama penangan Anda sebagai nilai atribut. Untuk informasi lebih lanjut, lihat Gambaran Umum Peristiwa yang Dirutekan.

Elemen bernama

Secara default, instans objek yang dibuat dalam grafik objek dengan memproses elemen objek XAML tidak memiliki pengidentifikasi unik atau referensi objek. Sebaliknya, jika Anda memanggil konstruktor dalam kode, Anda hampir selalu menggunakan hasil konstruktor untuk mengatur variabel ke instans yang dibuat, sehingga Anda dapat mereferensikan instans nanti dalam kode Anda. Untuk menyediakan akses standar ke objek yang dibuat melalui definisi markup, XAML mendefinisikan atribut x:Name. Anda dapat mengatur nilai atribut x:Name pada elemen objek apa pun. Di kode di Belakang Anda, pengidentifikasi yang Anda pilih setara dengan variabel instans yang merujuk ke instans yang dibuat. Dalam semua hal, elemen bernama berfungsi seolah-olah elemen tersebut adalah instans objek (nama mereferensikan instans tersebut), dan code-behind Anda dapat mereferensikan elemen bernama untuk menangani interaksi runtime dalam aplikasi. Hubungan antara instans dan variabel ini dilakukan oleh pengompilasi markup WPF XAML, dan lebih khusus lagi melibatkan fitur dan pola seperti InitializeComponent yang tidak akan dibahas secara mendetail dalam artikel ini.

Elemen XAML tingkat kerangka kerja WPF mewarisi properti Name, yang setara dengan atribut x:Name yang ditentukan XAML. Kelas tertentu lainnya juga menyediakan padanan tingkat properti untuk x:Name, yang juga biasanya didefinisikan sebagai properti Name. Secara umum, jika Anda tidak dapat menemukan properti Name di tabel anggota untuk elemen/jenis yang Anda pilih, gunakan x:Name sebagai gantinya. Nilai x:Name akan memberikan pengidentifikasi ke elemen XAML yang dapat digunakan saat runtime, baik oleh subsistem tertentu atau dengan metode utilitas seperti FindName.

Contoh berikut menetapkan Name pada elemen StackPanel. Kemudian, penangan pada Button di dalam StackPanel tersebut mereferensikan StackPanel melalui referensi instansnya buttonContainer sebagaimana ditetapkan oleh Name.

<StackPanel Name="buttonContainer">
    <Button Click="RemoveThis_Click">Click to remove this button</Button>
</StackPanel>
private void RemoveThis_Click(object sender, RoutedEventArgs e)
{
    var element = (FrameworkElement)e.Source;
    
    if (buttonContainer.Children.Contains(element))
        buttonContainer.Children.Remove(element);
}
Private Sub RemoveThis_Click(sender As Object, e As RoutedEventArgs)
    Dim element = DirectCast(e.Source, FrameworkElement)

    If buttonContainer.Children.Contains(element) Then
        buttonContainer.Children.Remove(element)
    End If
End Sub

Sama seperti variabel, nama XAML untuk sebuah instans diatur oleh konsep ruang lingkup, sehingga nama dapat dipaksakan menjadi unik dalam ruang lingkup tertentu yang dapat diprediksi. Markup utama yang mendefinisikan halaman menunjukkan satu namescope XAML yang unik, dengan batas namescope XAML menjadi elemen akar dari halaman tersebut. Namun, sumber markup lain dapat berinteraksi dengan halaman saat runtime, seperti gaya atau template dalam gaya, dan sumber markup tersebut sering kali memiliki cakupan nama XAML sendiri yang tidak harus terhubung dengan cakupan nama XAML halaman. Untuk informasi lebih lanjut tentang x:Name dan cakupan nama XAML, lihat Name, x:Name Directive, atau WPF XAML Namescopes.

Properti terlampir dan peristiwa terlampir

XAML menentukan fitur bahasa yang memungkinkan properti atau peristiwa tertentu ditentukan pada elemen apa pun, bahkan jika properti atau peristiwa tidak ada dalam definisi jenis untuk elemen yang sedang diatur. Versi properti dari fitur ini disebut properti terlampir, versi peristiwa disebut peristiwa terlampir. Secara konseptual, Anda dapat menganggap properti terlampir dan peristiwa terlampir sebagai anggota global yang dapat diatur pada instans elemen/objek XAML apa pun. Namun, elemen/kelas tersebut atau infrastruktur yang lebih besar harus mendukung penyimpanan properti pendukung untuk nilai yang dilampirkan.

Properti terlampir di XAML biasanya digunakan melalui sintaksis atribut. Dalam sintaksis atribut, Anda menentukan properti terlampir dalam bentuk ownerType.propertyName.

Sekilas, hal ini menyerupai penggunaan elemen properti, tetapi dalam kasus ini ownerType yang Anda tentukan selalu memiliki jenis yang berbeda dari elemen objek tempat properti terlampir sedang diatur. ownerType adalah jenis yang menyediakan metode pengakses yang diperlukan oleh prosesor XAML untuk mendapatkan atau mengatur nilai properti yang dilampirkan.

Skenario paling umum untuk properti terlampir adalah mengaktifkan elemen turunan untuk melaporkan nilai properti ke elemen induknya.

Contoh berikut mengilustrasikan properti terlampir DockPanel.Dock. Kelas DockPanel mendefinisikan pengakses untuk DockPanel.Dock dan memiliki properti terlampir. Kelas DockPanel juga menyertakan logika yang mengulangi elemen turunannya dan secara khusus memeriksa setiap elemen untuk nilai yang ditetapkan DockPanel.Dock. Jika nilai ditemukan, nilai tersebut digunakan selama tata letak untuk menempatkan elemen turunan. Penggunaan properti terlampir DockPanel.Dock dan kemampuan penempatan ini sebenarnya merupakan skenario yang memotivasi untuk kelas DockPanel.

<DockPanel>
    <Button DockPanel.Dock="Left" Width="100" Height="20">I am on the left</Button>
    <Button DockPanel.Dock="Right" Width="100" Height="20">I am on the right</Button>
</DockPanel>

Di WPF, sebagian besar atau semua properti terlampir juga diterapkan sebagai properti dependensi. Untuk informasi lebih lanjut, lihat Gambaran Umum Properti Terlampir.

Peristiwa terlampir menggunakan bentuk ownerType.eventName sintaksis atribut yang serupa. Sama seperti peristiwa tidak terlampir, nilai atribut untuk peristiwa terlampir di XAML menentukan nama metode penangan yang dipanggil saat peristiwa ditangani pada elemen. Penggunaan peristiwa terlampir di WPF XAML kurang umum. Untuk informasi lebih lanjut, lihat Gambaran Umum Peristiwa Terlampir.

Jenis dasar

WPF XAML yang mendasari dan namespace XAML-nya adalah kumpulan jenis yang sesuai dengan objek CLR dan elemen markup untuk XAML. Namun, tidak semua kelas dapat dipetakan ke elemen. Kelas abstrak, seperti ButtonBase, dan kelas dasar non-abstrak tertentu, digunakan untuk pewarisan dalam model objek CLR. Kelas dasar, termasuk kelas abstrak, masih penting untuk pengembangan XAML karena setiap elemen XAML konkret mewarisi anggota dari beberapa kelas dasar dalam hierarkinya. Seringkali anggota ini menyertakan properti yang dapat ditetapkan sebagai atribut pada elemen, atau peristiwa yang dapat ditangani. FrameworkElement adalah kelas UI dasar konkret WPF di tingkat kerangka kerja WPF. Saat mendesain UI, Anda akan menggunakan berbagai bentuk, panel, dekorator, atau kelas kontrol, yang semuanya berasal dari FrameworkElement. Kelas dasar terkait, FrameworkContentElement, mendukung elemen berorientasi dokumen yang berfungsi dengan baik untuk presentasi tata letak alur, menggunakan API yang secara sengaja mencerminkan API di FrameworkElement. Kombinasi atribut pada tingkat elemen dan model objek CLR memberi Anda seperangkat properti umum yang dapat diatur pada sebagian besar elemen XAML konkret, terlepas dari elemen XAML spesifik dan jenis dasarnya.

Keamanan

XAML adalah bahasa pemrogram markup yang secara langsung mewakili pembuatan dan eksekusi objek. Itulah sebabnya elemen yang dibuat di XAML memiliki kemampuan yang sama untuk berinteraksi dengan sumber daya sistem (akses jaringan, IO sistem file, misalnya) seperti yang dilakukan kode aplikasi Anda. XAML juga memiliki akses yang sama ke sumber daya sistem seperti halnya aplikasi hosting.

Keamanan Akses Kode (CAS) di WPF

Tidak seperti .NET Framework, WPF untuk .NET tidak mendukung CAS. Untuk informasi lebih lanjut, lihat Perbedaan Keamanan Akses Kode.

Memuat XAML dari kode

XAML dapat digunakan untuk mendefinisikan semua UI, tetapi terkadang juga tepat untuk mendefinisikan hanya sebagian UI di XAML. Kemampuan ini dapat digunakan untuk:

  • Mengaktifkan penyesuaian sebagian.
  • Penyimpanan lokal informasi UI.
  • Model objek bisnis.

Kunci dari skenario ini adalah kelas XamlReader dan metode Load-nya. Inputnya adalah file XAML, dan outputnya adalah objek yang mewakili semua pohon runtime objek yang dibuat dari markup tersebut. Anda kemudian dapat menyisipkan objek menjadi properti objek lain yang sudah ada di aplikasi. Selama properti berada dalam model konten dan memiliki kemampuan tampilan yang akan memberi tahu mesin eksekusi bahwa konten baru telah ditambahkan ke dalam aplikasi, Anda dapat memodifikasi konten aplikasi yang sedang berjalan dengan mudah dengan memuat secara dinamis di XAML.

Baca juga