Gambaran umum sumber daya XAML (WPF .NET)

Sumber daya adalah objek yang dapat digunakan kembali di berbagai tempat di aplikasi Anda. Contoh sumber daya termasuk kuas dan gaya. Gambaran umum ini menjelaskan cara menggunakan sumber daya dalam Extensible Application Markup Language (XAML). Anda juga dapat membuat dan mengakses sumber daya dengan menggunakan kode.

Catatan

Sumber daya XAML yang dijelaskan dalam artikel ini berbeda dari sumber daya aplikasi, yang umumnya merupakan file yang ditambahkan ke aplikasi, seperti konten, data, atau file yang disematkan.

Penting

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

Menggunakan sumber daya di XAML

Contoh berikut mendefinisikan SolidColorBrush sebagai sumber daya pada elemen akar halaman. Contoh kemudian mereferensikan sumber daya dan menggunakannya untuk mengatur properti dari beberapa elemen anak, termasuk Ellipse, , TextBlockdan Button.

<Window x:Class="resources.ResExample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ResExample" Height="400" Width="300">
    <Window.Resources>
        <SolidColorBrush x:Key="MyBrush" Color="#05E0E9"/>
        <Style TargetType="Border">
            <Setter Property="Background" Value="#4E1A3D" />
            <Setter Property="BorderThickness" Value="5" />
            <Setter Property="BorderBrush">
                <Setter.Value>
                    <LinearGradientBrush>
                        <GradientStop Offset="0.0" Color="#4E1A3D"/>
                        <GradientStop Offset="1.0" Color="Salmon"/>
                    </LinearGradientBrush>
                </Setter.Value>
            </Setter>
        </Style>
        <Style TargetType="TextBlock" x:Key="TitleText">
            <Setter Property="FontSize" Value="18"/>
            <Setter Property="Foreground" Value="#4E87D4"/>
            <Setter Property="FontFamily" Value="Trebuchet MS"/>
            <Setter Property="Margin" Value="0,10,10,10"/>
        </Style>
        <Style TargetType="TextBlock" x:Key="Label">
            <Setter Property="HorizontalAlignment" Value="Right"/>
            <Setter Property="FontSize" Value="13"/>
            <Setter Property="Foreground" Value="{StaticResource MyBrush}"/>
            <Setter Property="FontFamily" Value="Arial"/>
            <Setter Property="FontWeight" Value="Bold"/>
            <Setter Property="Margin" Value="0,3,10,0"/>
        </Style>
    </Window.Resources>

    <Border>
        <StackPanel>
            <TextBlock Style="{StaticResource TitleText}">Title</TextBlock>
            <TextBlock Style="{StaticResource Label}">Label</TextBlock>
            <TextBlock HorizontalAlignment="Right" FontSize="36" Foreground="{StaticResource MyBrush}" Text="Text" Margin="20" />
            <Button HorizontalAlignment="Left" Height="30" Background="{StaticResource MyBrush}" Margin="40">Button</Button>
            <Ellipse HorizontalAlignment="Center" Width="100" Height="100" Fill="{StaticResource MyBrush}" Margin="10" />
        </StackPanel>
    </Border>

</Window>

Setiap elemen tingkat kerangka kerja (FrameworkElement atau ) memiliki Resources properti , yang merupakan ResourceDictionary jenis yang berisi sumber FrameworkContentElementdaya yang ditentukan. Anda dapat menentukan sumber daya pada elemen apa pun, seperti Button. Namun, sumber daya paling sering didefinisikan pada elemen akar, yang ada Window dalam contoh.

Setiap sumber daya dalam kamus sumber daya harus memiliki kunci unik. Saat Anda menentukan sumber daya dalam markup, Anda menetapkan kunci unik melalui x:Key Directive. Biasanya, kuncinya adalah string; namun, Anda juga dapat mengaturnya ke jenis objek lain dengan menggunakan ekstensi markup yang sesuai. Kunci non-string untuk sumber daya digunakan oleh area fitur tertentu di WPF, terutama untuk gaya, sumber daya komponen, dan gaya data.

Anda dapat menggunakan sumber daya yang ditentukan dengan sintaks ekstensi markup sumber daya yang menentukan nama kunci sumber daya. Misalnya, gunakan sumber daya sebagai nilai properti pada elemen lain.

<Button Background="{StaticResource MyBrush}"/>
<Ellipse Fill="{StaticResource MyBrush}"/>

Dalam contoh sebelumnya, ketika pemuat XAML memproses nilai {StaticResource MyBrush} untuk Background properti pada Button, logika pencarian sumber daya terlebih dahulu memeriksa kamus sumber daya untuk elemen .Button Jika Button tidak memiliki definisi kunci MyBrush sumber daya (dalam contoh itu tidak; koleksi sumber dayanya kosong), pencarian berikutnya memeriksa elemen induk .Button Jika sumber daya tidak ditentukan pada induk, sumber daya akan terus memeriksa pohon logis objek ke atas hingga ditemukan.

Jika Anda menentukan sumber daya pada elemen akar, semua elemen di pohon logis, seperti Window atau Page, dapat mengaksesnya. Dan Anda dapat menggunakan kembali sumber daya yang sama untuk mengatur nilai properti apa pun yang menerima jenis yang sama dengan yang diwakili sumber daya. Dalam contoh sebelumnya, sumber daya yang sama MyBrush menetapkan dua properti berbeda: Button.Background dan Ellipse.Fill.

Sumber daya statis dan dinamis

Sumber daya dapat dirujuk sebagai statis atau dinamis. Referensi dibuat dengan menggunakan StaticResource Markup Extension atau DynamicResource Markup Extension. Ekstensi markup adalah fitur XAML yang memungkinkan Anda menentukan referensi objek dengan meminta ekstensi markup memproses string atribut dan mengembalikan objek ke pemuat XAML. Untuk informasi selengkapnya tentang perilaku ekstensi markup, lihat Ekstensi Markup dan WPF XAML.

Saat Anda menggunakan ekstensi markup, Anda biasanya menyediakan satu atau beberapa parameter dalam bentuk string yang diproses oleh ekstensi markup tertentu. Ekstensi Markup StaticResource memproses kunci dengan mencari nilai untuk kunci tersebut di semua kamus sumber daya yang tersedia. Pemrosesan terjadi selama beban, yaitu ketika proses pemuatan perlu menetapkan nilai properti. Ekstensi Markup DynamicResource sebagai gantinya memproses kunci dengan membuat ekspresi, dan ekspresi tersebut tetap tidak dievaluasi hingga aplikasi berjalan, saat ekspresi dievaluasi untuk memberikan nilai.

Saat Anda mereferensikan sumber daya, pertimbangan berikut dapat memengaruhi apakah Anda menggunakan referensi sumber daya statis atau referensi sumber daya dinamis:

  • Saat menentukan desain keseluruhan tentang cara Anda membuat sumber daya untuk aplikasi Anda (per halaman, di aplikasi, di XAML longgar, atau dalam rakitan khusus sumber daya), pertimbangkan hal berikut:

  • Fungsionalitas aplikasi. Apakah memperbarui sumber daya secara real-time merupakan bagian dari persyaratan aplikasi Anda?

  • Perilaku pencarian masing-masing dari jenis referensi sumber daya tersebut.

  • Properti atau jenis sumber daya tertentu, dan perilaku asli dari jenis tersebut.

Sumber daya statis

Referensi sumber daya statis berfungsi paling baik untuk keadaan berikut:

  • Desain aplikasi Anda memkonsentrasikan sebagian besar sumber dayanya ke dalam kamus sumber daya tingkat halaman atau aplikasi.

    Referensi sumber daya statis tidak dievaluasi ulang berdasarkan perilaku runtime, seperti memuat ulang halaman. Jadi mungkin ada beberapa manfaat performa untuk menghindari sejumlah besar referensi sumber daya dinamis saat tidak diperlukan berdasarkan sumber daya dan desain aplikasi Anda.

  • Anda mengatur nilai properti yang tidak ada di DependencyObject atau Freezable.

  • Anda membuat kamus sumber daya yang dikompilasi ke dalam DLL yang dibagikan antar aplikasi.

  • Anda membuat tema untuk kontrol kustom dan menentukan sumber daya yang digunakan dalam tema.

    Untuk kasus ini, Anda biasanya tidak ingin perilaku pencarian referensi sumber daya dinamis. Sebagai gantinya, gunakan perilaku referensi sumber daya statis sehingga pencarian dapat diprediksi dan mandiri ke tema. Dengan referensi sumber daya dinamis, bahkan referensi dalam tema dibiarkan tidak dievaluasi hingga run-time. Dan, ada kemungkinan bahwa ketika tema diterapkan, beberapa elemen lokal akan menentukan ulang kunci yang coba dirujuk tema Anda, dan elemen lokal akan jatuh sebelum tema itu sendiri dalam pencarian. Jika itu terjadi, tema Anda tidak akan berulah seperti yang diharapkan.

  • Anda menggunakan sumber daya untuk mengatur sejumlah besar properti dependensi. Properti dependensi memiliki penembolokan nilai yang efektif seperti yang diaktifkan oleh sistem properti, jadi jika Anda memberikan nilai untuk properti dependensi yang dapat dievaluasi pada waktu pemuatan, properti dependensi tidak perlu memeriksa ekspresi yang dievaluasi ulang dan dapat mengembalikan nilai efektif terakhir. Teknik ini bisa menjadi manfaat performa.

  • Anda ingin mengubah sumber daya yang mendasar untuk semua konsumen, atau Anda ingin mempertahankan instans bisa-tulis terpisah untuk setiap konsumen dengan menggunakan Atribut x:Shared.

Perilaku pencarian sumber daya statis

Berikut ini menjelaskan proses pencarian yang secara otomatis terjadi ketika sumber daya statis dirujuk oleh properti atau elemen:

  1. Proses pencarian memeriksa kunci yang diminta dalam kamus sumber daya yang ditentukan oleh elemen yang mengatur properti .

  2. Proses pencarian kemudian melintasi pohon logis ke atas ke elemen induk dan kamus sumber dayanya. Proses ini berlanjut hingga elemen akar tercapai.

  3. Sumber daya aplikasi diperiksa. Sumber daya aplikasi adalah sumber daya tersebut dalam kamus sumber daya yang ditentukan oleh Application objek untuk aplikasi WPF Anda.

Referensi sumber daya statis dari dalam kamus sumber daya harus mereferensikan sumber daya yang telah ditentukan secara leksikal sebelum referensi sumber daya. Referensi penerusan tidak dapat diselesaikan dengan referensi sumber daya statis. Untuk alasan ini, rancang struktur kamus sumber daya Anda sehingga sumber daya didefinisikan di atau dekat awal setiap kamus sumber daya masing-masing.

Pencarian sumber daya statis dapat meluas ke tema atau ke sumber daya sistem, tetapi pencarian ini hanya didukung karena pemuat XAML menangguhkan permintaan. Penahanan diperlukan agar tema runtime pada saat halaman dimuat berlaku dengan benar ke aplikasi. Namun, referensi sumber daya statis ke kunci yang diketahui hanya ada dalam tema atau karena sumber daya sistem tidak disarankan, karena referensi tersebut tidak dievaluasi ulang jika tema diubah oleh pengguna secara real time. Referensi sumber daya dinamis lebih dapat diandalkan saat Anda meminta tema atau sumber daya sistem. Pengecualiannya adalah ketika elemen tema itu sendiri meminta sumber daya lain. Referensi ini harus berupa referensi sumber daya statis, karena alasan yang disebutkan sebelumnya.

Perilaku pengecualian jika referensi sumber daya statis tidak ditemukan bervariasi. Jika sumber daya ditangguhkan, maka pengecualian terjadi pada runtime. Jika sumber daya tidak ditangguhkan, pengecualian terjadi pada waktu pemuatan.

Sumber daya dinamis

Sumber daya dinamis berfungsi paling baik ketika:

  • Nilai sumber daya, termasuk sumber daya sistem, atau sumber daya yang dapat diatur pengguna, tergantung pada kondisi yang tidak diketahui hingga runtime. Misalnya, Anda dapat membuat nilai setter yang merujuk ke properti sistem seperti yang diekspos oleh SystemColors, , SystemFontsatau SystemParameters. Nilai-nilai ini benar-benar dinamis karena pada akhirnya berasal dari lingkungan runtime pengguna dan sistem operasi. Anda mungkin juga memiliki tema tingkat aplikasi yang dapat berubah, di mana akses sumber daya tingkat halaman juga harus menangkap perubahan.

  • Anda membuat atau mereferensikan gaya tema untuk kontrol kustom.

  • Anda berniat untuk menyesuaikan konten ResourceDictionary selama masa pakai aplikasi.

  • Anda memiliki struktur sumber daya rumit yang memiliki interdependensi, di mana referensi penerusan mungkin diperlukan. Referensi sumber daya statis tidak mendukung referensi penerusan, tetapi referensi sumber daya dinamis mendukungnya karena sumber daya tidak perlu dievaluasi hingga runtime, dan referensi penerusan oleh karena itu bukan konsep yang relevan.

  • Anda mereferensikan sumber daya yang besar dari perspektif kompilasi atau set kerja, dan sumber daya mungkin tidak segera digunakan saat halaman dimuat. Referensi sumber daya statis selalu dimuat dari XAML saat halaman dimuat. Namun, referensi sumber daya dinamis tidak dimuat hingga digunakan.

  • Anda membuat gaya di mana nilai setter mungkin berasal dari nilai lain yang dipengaruhi oleh tema atau pengaturan pengguna lainnya.

  • Anda menerapkan sumber daya ke elemen yang mungkin direparasi di pohon logis selama masa pakai aplikasi. Mengubah induk juga berpotensi mengubah cakupan pencarian sumber daya, jadi jika Anda ingin sumber daya untuk elemen yang direparasi dievaluasi ulang berdasarkan cakupan baru, selalu gunakan referensi sumber daya dinamis.

Perilaku pencarian sumber daya dinamis

Perilaku pencarian sumber daya untuk referensi sumber daya dinamis menyejajarkan perilaku pencarian dalam kode Anda jika Anda memanggil FindResource atau SetResourceReference:

  1. Pencarian memeriksa kunci yang diminta dalam kamus sumber daya yang ditentukan oleh elemen yang mengatur properti:

  2. Pencarian melintasi pohon logis ke atas ke elemen induk dan kamus sumber dayanya. Proses ini berlanjut hingga elemen akar tercapai.

  3. Sumber daya aplikasi diperiksa. Sumber daya aplikasi adalah sumber daya tersebut dalam kamus sumber daya yang ditentukan oleh Application objek untuk aplikasi WPF Anda.

  4. Kamus sumber daya tema diperiksa untuk tema yang saat ini aktif. Jika tema berubah saat runtime, nilai dievaluasi ulang.

  5. Sumber daya sistem diperiksa.

Perilaku pengecualian (jika ada) bervariasi:

  • Jika sumber daya diminta oleh FindResource panggilan dan tidak ditemukan, pengecualian akan dilemparkan.

  • Jika sumber daya diminta oleh TryFindResource panggilan dan tidak ditemukan, tidak ada pengecualian yang dilemparkan, dan nilai yang dikembalikan adalah null. Jika properti yang ditetapkan tidak menerima null, maka masih mungkin bahwa pengecualian yang lebih dalam akan dilemparkan, tergantung pada properti individual yang ditetapkan.

  • Jika sumber daya diminta oleh referensi sumber daya dinamis di XAML dan tidak ditemukan, maka perilaku tergantung pada sistem properti umum. Perilaku umum seolah-olah tidak ada operasi pengaturan properti yang terjadi pada tingkat di mana sumber daya ada. Misalnya, jika Anda mencoba mengatur latar belakang pada elemen tombol individual menggunakan sumber daya yang tidak dapat dievaluasi, maka tidak ada hasil set nilai, tetapi nilai efektif masih dapat berasal dari peserta lain dalam sistem properti dan prioritas nilai. Misalnya, nilai latar belakang mungkin masih berasal dari gaya tombol yang ditentukan secara lokal atau dari gaya tema. Untuk properti yang tidak ditentukan oleh gaya tema, nilai efektif setelah evaluasi sumber daya yang gagal mungkin berasal dari nilai default dalam metadata properti.

Batasan

Referensi sumber daya dinamis memiliki beberapa batasan penting. Setidaknya salah satu kondisi berikut harus benar:

Karena properti yang diatur harus berupa DependencyProperty properti atau Freezable , sebagian besar perubahan properti dapat disebarluaskan ke UI karena perubahan properti (nilai sumber daya dinamis yang diubah) diakui oleh sistem properti. Sebagian besar kontrol menyertakan logika yang akan memaksa tata letak kontrol lain jika perubahan DependencyProperty dan properti tersebut mungkin memengaruhi tata letak. Namun, tidak semua properti yang memiliki DynamicResource Markup Extension sebagai nilainya dijamin untuk memberikan pembaruan real time di UI. Fungsionalitas tersebut mungkin masih bervariasi tergantung pada properti , dan tergantung pada jenis yang memiliki properti , atau bahkan struktur logis aplikasi Anda.

Gaya, DataTemplates, dan kunci implisit

Meskipun semua item dalam ResourceDictionary harus memiliki kunci, itu tidak berarti bahwa semua sumber daya harus memiliki eksplisit x:Key. Beberapa jenis objek mendukung kunci implisit saat didefinisikan sebagai sumber daya, di mana nilai kunci terikat dengan nilai properti lain. Jenis kunci ini dikenal sebagai kunci implisit, dan x:Key atribut adalah kunci eksplisit. Anda dapat menimpa kunci implisit apa pun dengan menentukan kunci eksplisit.

Salah satu skenario penting untuk sumber daya adalah ketika Anda menentukan Style. Bahkan, Style hampir selalu didefinisikan sebagai entri dalam kamus sumber daya, karena gaya secara inheren ditujukan untuk digunakan kembali. Untuk informasi selengkapnya tentang gaya, lihat Gaya dan templat (WPF .NET).

Gaya untuk kontrol dapat dibuat dengan dan direferensikan dengan kunci implisit. Gaya tema yang menentukan tampilan default kontrol bergantung pada kunci implisit ini. Dari sudut memintanya, kunci implisit adalah Type kontrol itu sendiri. Dari sudut penentuan sumber daya, kunci implisit adalah TargetType gaya. Dengan demikian, jika Anda membuat tema untuk kontrol kustom atau membuat gaya yang berinteraksi dengan gaya tema yang ada, Anda tidak perlu menentukan x:Key Directive untuk itu Style. Dan jika Anda ingin menggunakan gaya ber tema, Anda tidak perlu menentukan gaya apa pun sama sekali. Misalnya, definisi gaya berikut berfungsi, meskipun Style sumber daya tampaknya tidak memiliki kunci:

<Style TargetType="Button">
    <Setter Property="Background" Value="#4E1A3D" />
    <Setter Property="Foreground" Value="White" />
    <Setter Property="BorderThickness" Value="5" />
    <Setter Property="BorderBrush">
        <Setter.Value>
            <LinearGradientBrush>
                <GradientStop Offset="0.0" Color="#4E1A3D"/>
                <GradientStop Offset="1.0" Color="Salmon"/>
            </LinearGradientBrush>
        </Setter.Value>
    </Setter>
</Style>

Gaya itu benar-benar memiliki kunci: kunci implisit: jenisnya System.Windows.Controls.Button . Dalam markup, Anda dapat menentukan TargetType secara langsung sebagai nama jenis (atau Anda dapat secara opsional menggunakan {x:Type...} untuk mengembalikan Type.

Melalui mekanisme gaya tema default yang digunakan oleh WPF, gaya tersebut diterapkan sebagai gaya Button runtime pada halaman, meskipun Button itu sendiri tidak mencoba menentukan propertinya Style atau referensi sumber daya tertentu ke gaya. Gaya Anda yang ditentukan di halaman ditemukan sebelumnya dalam urutan pencarian daripada gaya kamus tema, menggunakan kunci yang sama dengan gaya kamus tema. Anda hanya dapat menentukan <Button>Hello</Button> di mana saja di halaman, dan gaya yang Anda tentukan TargetTypeButton akan berlaku untuk tombol itu. Jika mau, Anda masih dapat secara eksplisit kunci gaya dengan nilai jenis yang sama seperti TargetType untuk kejelasan dalam markup Anda, tetapi itu opsional.

Kunci implisit untuk gaya tidak berlaku pada kontrol jika OverridesDefaultStyle adalah true. (Perhatikan juga bahwa OverridesDefaultStyle mungkin ditetapkan sebagai bagian dari perilaku asli untuk kelas kontrol, daripada secara eksplisit pada instans kontrol.) Selain itu, untuk mendukung kunci implisit untuk skenario kelas turunan, kontrol harus mengambil alih DefaultStyleKey (semua kontrol yang ada yang disediakan sebagai bagian dari WPF termasuk penimpaan ini). Untuk informasi selengkapnya tentang gaya, tema, dan desain kontrol, lihat Panduan untuk Merancang Kontrol Yang Dapat Bergaya.

DataTemplate juga memiliki kunci implisit. Kunci implisit untuk adalah DataTemplateDataType nilai properti. DataType juga dapat ditentukan sebagai nama jenis daripada secara eksplisit menggunakan {x:Type...}. Untuk detailnya, lihat Gambaran Umum Templat Data.

Baca juga