Namescope XAML
Namescope XAML menyimpan hubungan antara nama objek yang ditentukan XAML dan setara instansnya. Konsep ini mirip dengan arti yang lebih luas dari istilah namescope dalam bahasa dan teknologi pemrograman lainnya.
Bagaimana namescope XAML ditentukan
Nama dalam namescope XAML memungkinkan kode pengguna untuk mereferensikan objek yang awalnya dideklarasikan dalam XAML. Hasil internal penguraian XAML adalah bahwa runtime membuat sekumpulan objek yang mempertahankan beberapa atau semua hubungan yang dimiliki objek ini dalam deklarasi XAML. Hubungan ini dipertahankan sebagai properti objek tertentu dari objek yang dibuat, atau diekspos ke metode utilitas dalam API model pemrograman.
Penggunaan nama yang paling umum dalam namescope XAML adalah sebagai referensi langsung ke instans objek, yang diaktifkan oleh pass kompilasi markup sebagai tindakan build proyek, dikombinasikan dengan metode InitializeComponent yang dihasilkan dalam templat kelas parsial.
Anda juga dapat menggunakan metode utilitas FindName sendiri pada waktu proses untuk mengembalikan referensi ke objek yang ditentukan dengan nama di markup XAML.
Selengkapnya tentang tindakan build dan XAML
Apa yang terjadi secara teknis adalah bahwa XAML sendiri menjalani compiler markup pass pada saat yang sama bahwa XAML dan kelas parsial yang ditentukan untuk code-behind dikompilasi bersama-sama. Setiap elemen objek dengan atribut Nama atau x:Name yang ditentukan dalam markup menghasilkan bidang internal dengan nama yang cocok dengan nama XAML. Bidang ini awalnya kosong. Kemudian kelas menghasilkan metode InitializeComponent yang hanya dipanggil setelah semua XAML dimuat. Dalam logika InitializeComponent, setiap bidang internal kemudian diisi dengan nilai pengembalian FindName untuk string nama yang setara. Anda dapat mengamati infrastruktur ini sendiri dengan melihat file ".g" (dihasilkan) yang dibuat untuk setiap halaman XAML di subfolder /obj proyek aplikasi Windows Runtime setelah kompilasi. Anda juga dapat melihat bidang dan metode InitializeComponent sebagai anggota rakitan yang Anda hasilkan jika Anda mencerminkannya atau memeriksa konten bahasa antarmukanya.
Catatan Khusus untuk aplikasi ekstensi komponen Visual C++ (C++/CX), bidang dukungan untuk referensi x:Name tidak dibuat untuk elemen akar file XAML. Jika Anda perlu mereferensikan objek akar dari C++/CX code-behind, gunakan API lain atau tree traversal. Misalnya Anda dapat memanggil FindName untuk elemen anak bernama yang diketahui lalu memanggil Induk.
Membuat objek pada waktu proses dengan XamlReader.Load
XAML juga dapat digunakan sebagai input string untuk metode XamlReader.Load , yang bertindak secara analog dengan operasi penguraian sumber XAML awal. XamlReader.Load membuat pohon objek baru yang terputus pada waktu proses. Pohon yang terputus kemudian dapat dilampirkan ke beberapa titik pada pohon objek utama. Anda harus secara eksplisit menyambungkan pohon objek yang Anda buat, baik dengan menambahkannya ke kumpulan properti konten seperti Anak-anak, atau dengan mengatur beberapa properti lain yang mengambil nilai objek (misalnya, memuat ImageBrush baru untuk nilai properti Isian).
Implikasi namescope XAML dari XamlReader.Load
Namescope XAML awal yang ditentukan oleh pohon objek baru yang dibuat oleh XamlReader.Load mengevaluasi nama yang ditentukan dalam XAML yang disediakan untuk keunikan. Jika nama dalam XAML yang disediakan tidak unik secara internal pada titik ini, XamlReader.Load akan memberikan pengecualian. Pohon objek yang terputus tidak mencoba menggabungkan namescope XAML-nya dengan namescope XAML aplikasi utama, jika atau ketika terhubung ke pohon objek aplikasi utama. Setelah menyambungkan pohon, aplikasi Anda memiliki pohon objek terpadu, tetapi pohon tersebut memiliki namescope XAML diskrit di dalamnya. Pembagian terjadi di titik koneksi antar objek, di mana Anda mengatur beberapa properti menjadi nilai yang dikembalikan dari panggilan XamlReader.Load .
Komplikasi memiliki namescope XAML yang diskrit dan terputus adalah bahwa panggilan ke metode FindName serta referensi objek terkelola langsung tidak lagi beroperasi terhadap namescope XAML terpadu. Sebagai gantinya, objek tertentu yang dipanggil FindName menyiratkan cakupan, dengan cakupan menjadi namescope XAML tempat objek panggilan berada. Dalam kasus referensi objek terkelola langsung, cakupan disiratkan oleh kelas tempat kode berada. Biasanya, code-behind untuk interaksi run-time dari "halaman" konten aplikasi ada di kelas parsial yang mendukung "halaman" akar, dan oleh karena itu namescope XAML adalah namescope XAML akar.
Jika Anda memanggil FindName untuk mendapatkan objek bernama di namescope XAML root, metode tidak akan menemukan objek dari namescope XAML diskrit yang dibuat oleh XamlReader.Load. Sebaliknya, jika Anda memanggil FindName dari objek yang diperoleh dari namescope XAML diskrit, metode tidak akan menemukan objek bernama di namescope XAML root.
Masalah namescope XAML diskrit ini hanya memengaruhi menemukan objek berdasarkan nama dalam namescope XAML saat menggunakan panggilan FindName .
Untuk mendapatkan referensi ke objek yang ditentukan dalam namescope XAML yang berbeda, Anda dapat menggunakan beberapa teknik:
- Berjalan di seluruh pohon dalam langkah-langkah diskrit dengan properti Induk dan/atau koleksi yang diketahui ada di struktur pohon objek Anda (seperti koleksi yang dikembalikan oleh Panel.Children).
- Jika Anda memanggil dari namescope XAML diskrit dan menginginkan namescope XAML akar, selalu mudah untuk mendapatkan referensi ke jendela utama yang saat ini ditampilkan. Anda bisa mendapatkan akar visual (elemen XAML akar, juga dikenal sebagai sumber konten) dari jendela aplikasi saat ini dalam satu baris kode dengan panggilan
Window.Current.Content
. Anda kemudian dapat mentransmisikan ke FrameworkElement dan memanggil FindName dari cakupan ini. - Jika Anda memanggil dari namescope XAML root dan menginginkan objek dalam namescope XAML diskrit, hal terbaik yang harus dilakukan adalah merencanakan ke depan dalam kode Anda dan mempertahankan referensi ke objek yang dikembalikan oleh XamlReader.Load lalu ditambahkan ke pohon objek utama. Objek ini sekarang menjadi objek yang valid untuk memanggil FindName dalam namescope XAML diskrit. Anda dapat menyimpan objek ini tersedia sebagai variabel global atau meneruskannya dengan menggunakan parameter metode.
- Anda dapat menghindari nama dan pertimbangan namescope XAML sepenuhnya dengan memeriksa pohon visual. Api VisualTreeHelper memungkinkan Anda melintasi pohon visual dalam hal objek induk dan koleksi anak, berdasarkan murni pada posisi dan indeks.
Namescope XAML dalam templat
Templat di XAML menyediakan kemampuan untuk menggunakan kembali dan menerapkan kembali konten dengan cara yang mudah, tetapi templat mungkin juga menyertakan elemen dengan nama yang ditentukan di tingkat templat. Templat yang sama mungkin digunakan beberapa kali dalam halaman. Untuk alasan ini, templat menentukan namescope XAML mereka sendiri, terlepas dari halaman yang berisi tempat gaya atau templat diterapkan. Pertimbangkan contoh ini:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Page.Resources>
<ControlTemplate x:Key="MyTemplate">
....
<TextBlock x:Name="MyTextBlock" />
</ControlTemplate>
</Page.Resources>
<StackPanel>
<SomeControl Template="{StaticResource MyTemplate}" />
<SomeControl Template="{StaticResource MyTemplate}" />
</StackPanel>
</Page>
Di sini, templat yang sama diterapkan ke dua kontrol yang berbeda. Jika templat tidak memiliki namescope XAML diskrit, nama "MyTextBlock" yang digunakan dalam templat akan menyebabkan tabrakan nama. Setiap instans templat memiliki namescope XAML sendiri, jadi dalam contoh ini setiap namescope XAML templat yang diinstansiasi akan berisi tepat satu nama. Namun, namescope XAML akar tidak berisi nama dari salah satu templat.
Karena namescope XAML terpisah, menemukan elemen bernama dalam templat dari cakupan halaman tempat templat diterapkan memerlukan teknik yang berbeda. Daripada memanggil FindName pada beberapa objek di pohon objek, Anda terlebih dahulu mendapatkan objek yang menerapkan templat, lalu memanggil GetTemplateChild. Jika Anda adalah penulis kontrol dan Anda membuat konvensi di mana elemen bernama tertentu dalam templat yang diterapkan adalah target untuk perilaku yang ditentukan oleh kontrol itu sendiri, Anda dapat menggunakan metode GetTemplateChild dari kode implementasi kontrol Anda. Metode GetTemplateChild dilindungi, jadi hanya pembuat kontrol yang memiliki akses ke metode tersebut. Selain itu, ada konvensi yang harus diikuti penulis kontrol untuk memberi nama bagian dan bagian templat dan melaporkannya sebagai nilai atribut yang diterapkan ke kelas kontrol. Teknik ini membuat nama bagian penting dapat ditemukan untuk mengontrol pengguna yang mungkin ingin menerapkan templat yang berbeda, yang perlu mengganti bagian bernama untuk mempertahankan fungsionalitas kontrol.