Bagikan melalui


Lingkup Nama di 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 proses kompilasi markup sebagai aksi pembangunan proyek, yang 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 XAML itu sendiri mengalami pemrosesan oleh kompiler tanda markup pada saat bersamaan ketika XAML dan kelas parsial yang ditentukannya untuk code-behind dikompailasi bersama. 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.

Nota

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 terpisah 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 dihasilkan oleh XamlReader.Load akan memeriksa keunikan nama-nama yang ditentukan dalam XAML yang disediakan. Jika nama dalam XAML yang disediakan tidak unik secara internal pada titik ini, XamlReader.Load akan memberikan pengecualian. Pohon objek yang terputus tidak berusaha untuk menggabungkan namescope XAML-nya dengan namescope XAML dari 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, kode-di-belakang untuk interaksi run-time dari "halaman" konten aplikasi ada di dalam kelas parsial yang mendukung "halaman" utama, dan oleh karena itu lingkup nama XAML adalah lingkup nama XAML utama.

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:

  • Menjelajahi seluruh pohon dalam tahapan diskret dengan properti Induk 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 induk, akan selalu mudah 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 sepenuhnya mengabaikan penggunaan nama dan pertimbangan skop nama XAML dengan memeriksa pohon visual. API VisualTreeHelper memungkinkan Anda melintasi pohon visual dalam hal objek induk dan koleksi anak, semata-mata berdasarkan posisi dan indeks.

Namescope XAML pada 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, independen dari halaman yang memuat 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 ruang nama XAML yang terpisah, nama "MyTextBlock" yang digunakan dalam templat akan menyebabkan benturan nama. Setiap instans templat memiliki namescope XAML sendiri, jadi dalam contoh ini setiap namescope XAML templat yang diinstansiasi akan berisi tepat satu nama. Namun, ruang lingkup nama akar XAML 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.