TOC

This article is currently in the process of being translated into Indonesian (~99% done).

A WPF application:

Resources

WPF memperkenalkan konsep yang sangat berguna: Kemampuannya untuk menyimpan data sebagai sumber, maupun lokal untuk sebuah kontrol, lokal untuk seluruh window atau secara global untuk seluruh aplikasi. Datanya dapat berupa apapun yang anda inginkan, dari informasi aktual ke sebuah hirarki dari kontrol WPF. Ini mengizinkan anda untuk menaruh data di satu tempat lalu menggunakannya dari atau beberapa tempat lainnya, yang mana sangat berguna.

Konsepnya banyak digunakan untuk style (gaya) dan template, yang akan kita diskusikan nanti di tutorial ini, tapi seperti yang akan di ilustrasikan di bab ini, anda bisa menggunakannya untuk hal-hal yang lain. Izinkan saya mendemonstrasikannya dengan contoh yang sederhana:

<Window x:Class="WpfTutorialSamples.WPF_Application.ResourceSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        Title="ResourceSample" Height="150" Width="350">
    <Window.Resources>
        <sys:String x:Key="strHelloWorld">Hello, world!</sys:String>
    </Window.Resources>
    <StackPanel Margin="10">
        <TextBlock Text="{StaticResource strHelloWorld}" FontSize="56" />
        <TextBlock>Just another "<TextBlock Text="{StaticResource strHelloWorld}" />" example, but with resources!</TextBlock>
    </StackPanel>
</Window>

Resource (sumber) diberikan sebuah key (kunci), menggunakan atribut x:Key, yang membolehkan anda untuk mereferensikannya dari bagian lain dari aplikasi dengan menggunakan key ini, dengan kombinasi dengan ekstensi markup StaticResource. Di contoh ini, Saya hanya menyimpan string yang sederhana, yang lalu akan saya gunakan dari dua kontrol TextBlock berbeda.

StaticResource vs. DynamicResource

Di contoh-contoh sejauh ini, Saya telah menggunakan ekstensi markup StaticResource untuk mereferensikan sebuah resource. Namun, sebuah ada alternatif, dalam bentuk DynamicResource.

Perbedaan utama adalah static resource hanya menyelesaikannya sekali, yang mana di poin dimana XAML itu dimuat. Jika resourcenya nanti diubah, perubahan ini tidak akan tercermin dimana anda menggunakan StaticResource.

Sebaliknya, DynamicResource diselesaikan setelah itu benar-benar diperlukan, lalu lagi-lagi jika resourcenya berubah. Pikirkan itu sebagai binding ke nilai static vs. binding ke sebuah fungsi yang memonitori nilai ini dan mengirimnya ke anda setiap kali itu berubah - Itu bukan cara kerjanya, tapi itu akan memberikan anda ide yang lebih baik kapan kali itu digunakan. Dynamic resources juga membolehkan anda untuk menggunakan resource yang bahkan tidak disana diwaktu mendesain, contoh jika anda menambahkan mereka dari Code-Behind pada saat memulai aplikasi.

Tipe resource lebih

Membagikan sebuah string sederhana sangat mudah, tapi anda bisa melakukannya lebih banyak lagi. Di contoh berikutnya, Saya juga akan menyimpan sebuah array string yang lengkap. bersama dengan kuas gradien yang akan digunakan untuk background. Ini akan memberikan anda ide yang cukup bagus tentang seberapa banyak yang bisa anda lakukan dengan resource:

<Window x:Class="WpfTutorialSamples.WPF_Application.ExtendedResourceSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        Title="ExtendedResourceSample" Height="160" Width="300"
        Background="{DynamicResource WindowBackgroundBrush}">
    <Window.Resources>
        <sys:String x:Key="ComboBoxTitle">Items:</sys:String>

        <x:Array x:Key="ComboBoxItems" Type="sys:String">
            <sys:String>Item #1</sys:String>
            <sys:String>Item #2</sys:String>
            <sys:String>Item #3</sys:String>
        </x:Array>

        <LinearGradientBrush x:Key="WindowBackgroundBrush">
            <GradientStop Offset="0" Color="Silver"/>
            <GradientStop Offset="1" Color="Gray"/>
        </LinearGradientBrush>
    </Window.Resources>
    <StackPanel Margin="10">
        <Label Content="{StaticResource ComboBoxTitle}" />
        <ComboBox ItemsSource="{StaticResource ComboBoxItems}" />
    </StackPanel>
</Window>

Kali ini, kita telah menambahkan beberapa resource ekstra, jadi Window kita sekarang berisi sebuah string sederhana, sebuah array string dan sebuah LinearGradientBrush. stringnya digunakan untuk label, array stringnya digunakan sebagai item untuk kontrol ComboBox dan kuas gradiennya digunakan sebagai background untuk seluruh window. Jadi, seperti yang bisa anda lihat, banyak sekali hal yang bisa kita simpan sebagai resource.

Lokal dan aplikasi wide resources

Untuk sekarang, kita telah menyimpan resource di sebuah window-level, yang berarti anda dapat mengakses mereka dari seluruh window.

Jika anda hanya butuh memberikan sebuah resource untuk kontrol yang spesifik, anda dapat membuatnya lebih lokal dengan menambahkannya ke kontrol yang spesifik ini, daripada ke window. Itu bekerja persis dengan cara yang sama, satu-satunya perbedaan dari itu anda sekarang hanya dapat mengakses dari dalam scope kontrol dimana anda menaruhnya:

<StackPanel Margin="10">
    <StackPanel.Resources>
        <sys:String x:Key="ComboBoxTitle">Items:</sys:String>
    </StackPanel.Resources>
    <Label Content="{StaticResource ComboBoxTitle}" />
</StackPanel>

Di situasi ini, kita telah menambahkan resource ke StackPanel lalu menggunakannya dari kontrol anak tersebut, Label. Kontrol lain didalam StackPanel bisa juga menggunakannya, hanya seperti anak dari kontrol anak ini akan bisa mengaksesnya. Kontrol diluar dari StackPanel khusus ini tidak akan mendapatkan akses kesana.

Jika anda ingin kemampuan untuk mengakses resource dari beberapa window, ini mungkin juga bisa. File App.xamlnya dapat berisi resource sama seperti window dan segala jenis kontrol WPF, lalu anda menyimpan mereka di App.xaml, mereka dapat diakses secara global di semua window dan kontrol pengguna (user control) dari sebuah project. Itu bekerja persis dengan cara yang sama seperti ketika menyimpan dan menggunakan dari sebuah Window:

<Application x:Class="WpfTutorialSamples.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:sys="clr-namespace:System;assembly=mscorlib"
             StartupUri="WPF application/ExtendedResourceSample.xaml">
    <Application.Resources>
        <sys:String x:Key="ComboBoxTitle">Items:</sys:String>
    </Application.Resources>
</Application>

Menggunakannya juga sama - WPF akan otomatis pergi keatas scope, dari kontrol lokal ke window lalu ke App.xaml, untuk menemukan resource yang diberikan:

<Label Content="{StaticResource ComboBoxTitle}" />

Resource dari Code-Behind

Sejauh ini, kita telah mengakses kesemua dari resource kami langsung dari XAML, menggunakan ekstensi markup. Walaupun, anda tentu saja dapat mengakses resource anda dari Code-Behind juga, yang dapat menjadi berguna di beberapa situasi. Di contoh sebelumnya, kita telah menyaksikan bagaimana kita menyimpan resource di beberapa tempat yang berbeda, jadi di contoh ini, kita akan bisa mengakses tiga resource berbeda dari Code-Behind, setiapnya tersimpan di sebuah scope yang berbeda:

App.xaml:

<Application x:Class="WpfTutorialSamples.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:sys="clr-namespace:System;assembly=mscorlib"
             StartupUri="WPF application/ResourcesFromCodeBehindSample.xaml">
    <Application.Resources>
        <sys:String x:Key="strApp">Hello, Application world!</sys:String>
    </Application.Resources>
</Application>

Window:

<Window x:Class="WpfTutorialSamples.WPF_Application.ResourcesFromCodeBehindSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        Title="ResourcesFromCodeBehindSample" Height="175" Width="250">
    <Window.Resources>
        <sys:String x:Key="strWindow">Hello, Window world!</sys:String>
    </Window.Resources>
    <DockPanel Margin="10" Name="pnlMain">
        <DockPanel.Resources>
            <sys:String x:Key="strPanel">Hello, Panel world!</sys:String>
        </DockPanel.Resources>

        <WrapPanel DockPanel.Dock="Top" HorizontalAlignment="Center" Margin="10">
            <Button Name="btnClickMe" Click="btnClickMe_Click">Click me!</Button>
        </WrapPanel>

        <ListBox Name="lbResult" />
    </DockPanel>
</Window>

Code-behind:

using System;
using System.Windows;

namespace WpfTutorialSamples.WPF_Application
{
	public partial class ResourcesFromCodeBehindSample : Window
	{
		public ResourcesFromCodeBehindSample()
		{
			InitializeComponent();
		}

		private void btnClickMe_Click(object sender, RoutedEventArgs e)
		{
			lbResult.Items.Add(pnlMain.FindResource("strPanel").ToString());
			lbResult.Items.Add(this.FindResource("strWindow").ToString());
			lbResult.Items.Add(Application.Current.FindResource("strApp").ToString());
		}
	}
}

Jadi, seperti yang bisa anda lihat, kita menyimpan tiga pesan "Hello, world!" di tempat yang berbeda: Satu di App.xaml, satu didalam window, dan satu secara lokal untuk panel utama. Antarmukanya terdiri dari sebuah button dan sebuah ListBox.

Di Code-Behind, kita menangani event klik dari button, yang mana kita menambahkan masing-masing teks string ke ListBox, seperti yang terlihat di screenshot. Kita menggunakan method FindResource(), yang akan meng-return (mengembalikan) sebuah object resource (jika ketemu), lalu mengubahnya ke sebuah string yang kita tahu itu dengan menggunakan method ToString().

Perhatikan bagaimana kita menggunakan method FindResource() di scope yang berbeda - Pertama di panel, lalu di window lalu di object Aplikasi sekarang. Masuk akal untuk mencari resource yang mana kita tahu itu, tapi seperti yang sudah disebutkan, jika sebuah resource tidak ditemukan, proses pencarian itu berlanjut ke hirarki, jadi pada prinsipnya, kita dapat menggunakan method FindResource() di panel didalam semua tiga kasus, karena akan terus ke window dan kemudian ke tingkat aplikasi, jika tidak ditemukan.

Hal yang sama tidak benar, sebaliknya - pencariannya tidak menavigasi pohonnya kebawah, jadi anda tidak bisa memulai mencari sebuah resource di tingkat aplikasi, jika itu telah didefinisikan secara lokal untuk kontrolnya atau untuk windownya.

This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!