Bagikan melalui


Cakupan Nama WPF XAML

Namescope XAML adalah konsep yang mengidentifikasi objek yang ditentukan dalam XAML. Nama dalam namescope XAML dapat digunakan untuk membangun hubungan antara nama objek yang ditentukan XAML dan instansnya yang setara di pohon objek. Biasanya, namescope XAML dalam kode terkelola WPF dibuat saat memuat akar halaman XAML individual untuk aplikasi XAML. Namescope XAML sebagai objek pemrograman didefinisikan oleh INameScope antarmuka dan juga diimplementasikan oleh kelas NameScopepraktis .

Namescope dalam Aplikasi XAML yang Dimuat

Dalam konteks pemrograman atau ilmu komputer yang lebih luas, konsep pemrograman sering kali mencakup prinsip pengidentifikasi atau nama unik yang dapat digunakan untuk mengakses objek. Untuk sistem yang menggunakan pengidentifikasi atau nama, namescope menentukan batas di mana proses atau teknik akan mencari apakah objek nama tersebut diminta, atau batas di mana keunikan mengidentifikasi nama diberlakukan. Prinsip-prinsip umum ini berlaku untuk namescope XAML. Di WPF, namescope XAML dibuat pada elemen root untuk halaman XAML saat halaman dimuat. Setiap nama yang ditentukan dalam halaman XAML yang dimulai dari akar halaman ditambahkan ke namescope XAML yang bersangkutan.

Dalam WPF XAML, elemen yang merupakan elemen akar umum (seperti Page, dan Window) selalu mengontrol namescope XAML. Jika elemen seperti FrameworkElement atau FrameworkContentElement adalah elemen akar halaman dalam markup, prosesor XAML menambahkan akar secara implisit Page sehingga Page dapat menyediakan namescope XAML yang berfungsi.

Catatan

Tindakan build WPF membuat namescope XAML untuk produksi XAML meskipun tidak ada Name atau x:Name atribut yang ditentukan pada elemen apa pun dalam markup XAML.

Jika Anda mencoba menggunakan nama yang sama dua kali dalam namescope XAML apa pun, pengecualian akan dinaikkan. Untuk WPF XAML yang memiliki code-behind dan merupakan bagian dari aplikasi yang dikompilasi, pengecualian dinaikkan pada waktu build oleh tindakan build WPF, saat membuat kelas yang dihasilkan untuk halaman selama kompilasi markup awal. Untuk XAML yang tidak dikompilasi markup oleh tindakan build apa pun, pengecualian yang terkait dengan masalah namescope XAML mungkin muncul saat XAML dimuat. Desainer XAML mungkin juga mengantisipasi masalah namescope XAML pada waktu desain.

Menambahkan Objek ke Pohon Objek Runtime

Momen saat XAML diurai mewakili momen pada saat namescope WPF XAML dibuat dan ditentukan. Jika Anda menambahkan objek ke pohon objek pada titik waktu setelah XAML yang menghasilkan pohon tersebut diurai, Name nilai atau x:Name pada objek baru tidak secara otomatis memperbarui informasi dalam namescope XAML. Untuk menambahkan nama objek ke dalam namescope WPF XAML setelah XAML dimuat, Anda harus memanggil implementasi yang sesuai pada RegisterName objek yang menentukan namescope XAML, yang biasanya merupakan akar halaman XAML. Jika nama tidak terdaftar, objek yang ditambahkan tidak dapat direferensikan berdasarkan nama melalui metode seperti FindName, dan Anda tidak dapat menggunakan nama tersebut untuk penargetan animasi.

Skenario paling umum untuk pengembang aplikasi adalah Anda akan menggunakan RegisterName untuk mendaftarkan nama ke dalam namescope XAML pada akar halaman saat ini. RegisterName adalah bagian dari skenario penting untuk papan cerita yang menargetkan objek untuk animasi. Untuk informasi selengkapnya, lihat Gambaran Umum Papan Cerita.

Jika Anda memanggil RegisterName objek selain objek yang menentukan namescope XAML, nama masih terdaftar ke namescope XAML tempat objek panggilan disimpan, seolah-olah Anda telah memanggil RegisterName objek pendefinisian namescope XAML.

Namescope XAML dalam Kode

Anda dapat membuat lalu menggunakan namescope XAML dalam kode. API dan konsep yang terlibat dalam pembuatan namescope XAML sama bahkan untuk penggunaan kode murni, karena prosesor XAML untuk WPF menggunakan API dan konsep ini ketika memproses XAML itu sendiri. Konsep dan API ada terutama untuk tujuan dapat menemukan objek berdasarkan nama dalam pohon objek yang biasanya didefinisikan sebagian atau seluruhnya dalam XAML.

Untuk aplikasi yang dibuat secara terprogram, dan bukan dari XAML yang dimuat, objek yang mendefinisikan namescope XAML harus menerapkan INameScope, atau menjadi FrameworkElement kelas atau FrameworkContentElement turunan, untuk mendukung pembuatan namescope XAML pada instansnya.

Selain itu, untuk elemen apa pun yang tidak dimuat dan diproses oleh prosesor XAML, namescope XAML untuk objek tidak dibuat atau diinisialisasi secara default. Anda harus secara eksplisit membuat namescope XAML baru untuk objek apa pun yang ingin Anda daftarkan namanya kemudian. Untuk membuat namescope XAML, Anda memanggil metode statis SetNameScope . Tentukan objek yang akan memilikinya sebagai dependencyObject parameter, dan panggilan konstruktor baru NameScope sebagai value parameter .

Jika objek yang disediakan sebagai dependencyObjectSetNameScope untuk bukan INameScope implementasi, FrameworkElement atau FrameworkContentElement, memanggil elemen turunan RegisterName apa pun tidak akan berpengaruh. Jika Anda gagal membuat namescope XAML baru secara eksplisit, maka panggilan ke RegisterName akan menimbulkan pengecualian.

Untuk contoh penggunaan API namescope XAML dalam kode, lihat Menentukan Cakupan Nama.

Namescope XAML dalam Gaya dan Templat

Gaya dan templat di WPF menyediakan kemampuan untuk menggunakan kembali dan menerapkan kembali konten dengan cara yang mudah. Namun, gaya dan templat mungkin juga menyertakan elemen dengan nama XAML yang ditentukan pada tingkat templat. Templat yang sama mungkin digunakan beberapa kali dalam halaman. Untuk alasan ini, gaya dan templat menentukan namescope XAML mereka sendiri, terlepas dari lokasi apa pun di pohon objek tempat gaya atau templat diterapkan.

Pertimbangkan contoh berikut:

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  >
  <Page.Resources>
    <ControlTemplate x:Key="MyButtonTemplate" TargetType="{x:Type Button}">
      <Border BorderBrush="Red" Name="TheBorder" BorderThickness="2">
        <ContentPresenter/>
      </Border>      
    </ControlTemplate>
  </Page.Resources>
  <StackPanel>
    <Button Template="{StaticResource MyButtonTemplate}">My first button</Button>
    <Button Template="{StaticResource MyButtonTemplate}">My second button</Button>
  </StackPanel>
</Page>

Di sini, templat yang sama diterapkan ke dua tombol yang berbeda. Jika templat tidak memiliki namescope XAML diskrit, nama yang TheBorder digunakan dalam templat akan menyebabkan tabrakan nama di namescope XAML. Setiap instans templat memiliki namescope XAML sendiri, jadi dalam contoh ini setiap namescope XAML templat yang diinstansiasi akan berisi tepat satu nama.

Gaya juga mendefinisikan namescope XAML mereka sendiri, sebagian besar sehingga bagian papan cerita dapat memiliki nama tertentu yang ditetapkan. Nama-nama ini memungkinkan kontrol perilaku tertentu yang akan menargetkan elemen nama tersebut, bahkan jika templat didefinisikan kembali sebagai bagian dari kustomisasi kontrol.

Karena namescope XAML terpisah, menemukan elemen bernama dalam templat lebih menantang daripada menemukan elemen bernama non-templat di halaman. Pertama-tama Anda perlu menentukan templat yang diterapkan, dengan mendapatkan Template nilai properti kontrol tempat templat diterapkan. Kemudian, Anda memanggil versi FindNametemplat , meneruskan kontrol tempat templat diterapkan sebagai parameter kedua.

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 GetTemplateChild metode dari kode implementasi kontrol Anda. Metode GetTemplateChild ini dilindungi, jadi hanya pembuat kontrol yang memiliki akses ke metode tersebut.

Jika Anda bekerja dari dalam templat, dan perlu masuk ke namescope XAML tempat templat diterapkan, dapatkan nilai TemplatedParent, lalu panggil FindName di sana. Contoh bekerja dalam templat adalah jika Anda menulis implementasi penanganan aktivitas di mana peristiwa akan dinaikkan dari elemen dalam templat yang diterapkan.

FrameworkElement memiliki FindNamemetode , RegisterName dan UnregisterName . Jika objek yang Anda sebut metode ini memiliki namescope XAML, metode memanggil ke metode namescope XAML yang relevan. Jika tidak, elemen induk diperiksa untuk melihat apakah ia memiliki namescope XAML, dan proses ini berlanjut secara rekursif sampai namescope XAML ditemukan (karena perilaku prosesor XAML, dijamin ada namescope XAML di akar). FrameworkContentElement memiliki perilaku analog, dengan pengecualian bahwa tidak FrameworkContentElement akan pernah memiliki namescope XAML. Metode ada sehingga panggilan dapat diteruskan FrameworkContentElement pada akhirnya ke FrameworkElement elemen induk.

SetNameScope digunakan untuk memetakan namescope XAML baru ke objek yang sudah ada. Anda dapat memanggil SetNameScope lebih dari sekali untuk mengatur ulang atau menghapus namescope XAML, tetapi itu bukan penggunaan umum. Selain itu, GetNameScope biasanya tidak digunakan dari kode.

Implementasi Namescope XAML

Kelas-kelas berikut mengimplementasikan INameScope secara langsung:

ResourceDictionary tidak menggunakan nama atau namescope XAML; sebaliknya menggunakan kunci, karena merupakan implementasi kamus. Satu-satunya alasan yang ResourceDictionary mengimplementasikan INameScope adalah sehingga dapat menimbulkan pengecualian untuk kode pengguna yang membantu mengklarifikasi perbedaan antara namescope XAML sejati dan cara ResourceDictionary menangani kunci, dan juga untuk memastikan bahwa namescope XAML tidak diterapkan ke ResourceDictionary elemen induk.

FrameworkTemplate dan Style terapkan INameScope melalui definisi antarmuka eksplisit. Implementasi eksplisit memungkinkan namescope XAML ini berprilaku konvensional ketika diakses melalui INameScope antarmuka, yaitu bagaimana namescope XAML dikomunikasikan oleh proses internal WPF. Tetapi definisi antarmuka eksplisit bukan bagian dari permukaan FrameworkTemplate API konvensional dan Style, karena Anda jarang perlu memanggil INameScope metode pada FrameworkTemplate dan Style secara langsung, dan sebaliknya akan menggunakan API lain seperti GetTemplateChild.

Kelas berikut menentukan namescope XAML mereka sendiri, dengan menggunakan System.Windows.NameScope kelas pembantu dan menyambungkan ke implementasi namescope XAML-nya melalui NameScope.NameScope properti terlampir:

Baca juga