Namescope XAML

Namescope XAML menyimpan hubungan antara nama objek yang ditentukan XAML dan instansnya yang setara. 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 durasi 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 itu sendiri mengalami kompilator markup lulus pada saat yang sama bahwa XAML dan kelas parsial yang ditentukan untuk kode-di belakang 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 dipanggil hanya 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 antarmuka mereka.

Catatan Khusus untuk aplikasi ekstensi komponen Visual C++ (C++/CX), bidang cadangan untuk referensi x:Name tidak dibuat untuk elemen akar file XAML. Jika Anda perlu mereferensikan objek akar dari kode C++/CX di belakang, gunakan API atau traversal pohon lainnya. Misalnya, Anda dapat memanggil FindName untuk elemen anak bernama yang diketahui lalu memanggil Induk.

Membuat objek pada durasi 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 durasi. 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 saat ini, XamlReader.Load 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 pada titik koneksi antara 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. Sebaliknya, 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 akar, 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 akar.

Masalah namescope XAML diskrit ini hanya memengaruhi penemuan 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 akar 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. VisualTreeHelper API 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 pada 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 instansiasi templat memiliki namescope XAML sendiri, jadi dalam contoh ini setiap namescope XAML templat yang dibuat 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.