Ogni FrameworkElement espone una proprietà Resources che contiene tutte le risorse associate, la proprietà è di tipo ResourceDictionary che fondamentalmente è una HashTable ottimizzata in quanto gli item contenuti vengono parsificati on demand.
Sebbene sia possibile definire le risorse a livello di FrameworkElement essendo solitamente le risorse condivise tra le varie parti che compongono l'applicazione solitamente queste vengono definite o all'interno di una Window oppure direttamente a livello di applicazione nel file App.xaml.
<StackPanel>
<StackPanel.Resources>
<LinearGradientBrush x:Key="b1" StartPoint="0,0" EndPoint="1,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="RoyalBlue" Offset="0"/>
<GradientStop Color="Aqua" Offset="1"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<CheckBox x:Key="c1" HorizontalAlignment="Center">Ciao</CheckBox>
<ControlTemplate x:Key="i1">
<Image Source="Giulia.jpg" Width="150" Height="100"/>
</ControlTemplate>
</StackPanel.Resources>
<Button Width="100" Height="75" Background="{StaticResource b1}" />
<Button VerticalAlignment="Bottom" Width="100" Height="75" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<StaticResource ResourceKey="c1"/>
<Control Template="{StaticResource i1}" />
<Button Template="{StaticResource i1}" />
</StackPanel>
Nell'esempio sopra indicato nello StackPanel che contiene vari buttons (e non solo) sono definite alcune risorse ognuna identificata da una propria chiave (x:Key="..."), notate che all'interno di un insieme di risorse è possibile mettere qualsiasi elemento, FrameworkElements inclusi, come nel caso della CheckBox anche se in questo caso c'è la limitazione di poterla utilizzare una sola volta.
Per utilizzare le risorse contenute nel ResourceDictionary dello StackPanel vengono utilizzate delle MarkupExtensions (riconoscibili perche sono contenute tra parentesi graffe), nel caso specifico del primo Button il colore di sfondo è associato staticamente alla risorsa b1 mediante Background="{StaticResource b1}".
Quando WPF deve risolvere questa associazione cerca nelle risorse dell'elemento interessato, ovvero il pulsante, se la risorsa non viene identificata, la ricerca passa al parent (lo StackPanel) e, se anche qui non viene trovata al rispettivo parent fino a raggiungere le risorse associate all'applicazione ed eventualmente le risorse di sistema.
Usando StaticResource l'associazione avviene a load time e quindi se la risorsa viene successivamente modificata, l'associazione non cambia.
Volendo creare un associazione dinamica, ad esempio perchè si fa uso di risorse che possono cambiare durante la vita dell'applicazione la sintassi da utilizzare è leggermente diversa in quanto si utilizza una DynamicResourceExtension come nel caso del secondo pulsante il cui colore di sfondo è legato alla proprietà statica SystemColors.ControlBrushKey, e questo spiega la presenza della markup extension x:Static.
Volendo è possibile inserire una risorsa direttamente utilizzando il tag StaticResource come nel caso sopra riportato anche se, volendo riutilizzare lo stesso elemento più volte è necessario inserirlo all'interno di un ControlTemplate come nel caso dell'elemento Image.
Come mostrato nei precedenti posts le risorse sono la posizione ottimale per definire gli stili applicati ai vari controlli sopratutto perchè essendo possibile cambiare dinamicamente le risorse di applicazione, realizzare un applicazione "Skinnabile" si traduce nel definire i vari stili, caricarli e associarli all'applicazione usando:
ResourceDictionary newSkin= LoadNewSkin();
Application.Current.Resources = newSkin;
Ottenendo in questo caso l'aggiornamento automatico della user interface.
Per quanto riguarda le risorse "tradizionali" ovvero immagini, dati binari, file audio etc..., è sufficiente aggiungerle al progetto e Visual Studio provvederà ad associarne la Build Action a Resource facendole diventare parte integrante del manifest all'interno del quale vengono memorizzate tutte le risorse WPF.
A questo punto è possibile referenziale direttamente da XAML come nella sezione:
<Image Source="Giulia.jpg" Width="150" Height="100"/>