WPF resource system allows you to keep
useful objects around you so you can reuse easily. There are multiple ways
to define Resources in WPF. In this post I will explain all the ways where we
can define and use resources. Resource element defines a resource dictionary and dictionary requires every item to have key, so we must provide key to every resource declared inside resource dictionary.
Declaring resource inside element’s
resources property -
You can
declare resources which are going to be used inside your current window those resources
can be declared inside Window.Resources
element. In fact almost every resource in WPF has resources property so you can
set anywhere you want. But the resources are accessible to the element and its child elements. Resources declared at top element (root level element) can be accessible to every
element in window. In below example I have declared
resources in window.resources element so every elements of window will have access those resources.
<Window x:Class="WpfApplication1.WPFResourcesDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WPF Resources"
Height="100" Width="300">
<Window.Resources>
<LinearGradientBrush x:Key="linearGradientforButton">
<GradientStop Color="Blue" Offset="0"/>
<GradientStop Color="White" Offset="0.5"/>
<GradientStop Color="Cyan" Offset="1"/>
</LinearGradientBrush>
<Style TargetType="Button" x:Key="ButtonStyle">
<Setter Property="Width" Value="150" />
<Setter Property="Height" Value="40" />
<Setter Property="HorizontalAlignment" Value="Center"
/>
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="Margin" Value="10" />
</Style>
</Window.Resources>
<Grid>
<Button Name="MyButton"
Content="Click Me!"
Background="{StaticResource
linearGradientforButton}"
Style="{StaticResource ButtonStyle}" />
</Grid>
</Window>
In above
example, two resources are declared and both are used by one button. If you
have multiple buttons in the same window, all the buttons will have access to
the resources defined in window’s resources element. All the resource must be
uniquely identified by x:key name
inside resource dictionary. Similarly element can access those using StaticResource markup extension.
In WPF logical tree, almost every control has resource dictionaries.
When any control uses resource, WPF look
upward through the tree until it finds an object defined in resource with given
key. In above example, Button’s background and style property uses resource
from resource dictionary. So WPF will look upwards and it will find resource declared
in window’s resource dictionary.
Declaring Resources in App.xaml -
As shown in
above example, if control uses resource then WPF look upwards till root object
e.g. window but if the resource is not declared at root level then it will look
in Application.Resources element of App.xaml file. The resources are declared
in app.xaml file will be accessible to all windows inside application. So when resources
are used by multiple windows, app.xaml file will be the best suitable place to
declare those resources.
Let’s have a
look on below code.
<Window x:Class="WpfApplication1.WPFResourcesDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WPF Resources"
Height="100" Width="300">
<Grid>
<Button Name="MyButton"
Content="Click Me!"
Background="{StaticResource linearGradientforButton}"
Style="{StaticResource ButtonStyle}" />
</Grid>
</Window>
app.xaml
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="WPFResourcesDemo.xaml">
<Application.Resources>
<LinearGradientBrush x:Key="linearGradientforButton">
<GradientStop Color="Blue" Offset="0"/>
<GradientStop Color="White" Offset="0.5"/>
<GradientStop Color="Cyan" Offset="1"/>
</LinearGradientBrush>
<Style TargetType="Button" x:Key="ButtonStyle">
<Setter Property="Width" Value="150" />
<Setter Property="Height" Value="40" />
<Setter Property="HorizontalAlignment" Value="Center"
/>
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="Margin" Value="10" />
</Style>
</Application.Resources>
</Application>
The output of
this code will be the same as first example. In this example resources are
declared in Application.Resources element of App.XAML file
Declaring resources in separate Resource Dictionary -
WPF allows
you to keep your all the resources at single place called resource dictionary file.
Resource dictionary file has root element called ResourceDictionary. If your
application has lots of resources and you want declare those resources inside
app.xaml the file will be too large and difficult to manage and also it is not
good practice to place so many resources inside app.xaml. In this case you should
go for separate file called ResourceDictionary. You should place different resources in multiple resources file and merge it in window. You can create multiple resource
dictionary files and merge those files inside your main window.
Let’s have a look on below code.
ResourceDictionary.Xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<LinearGradientBrush x:Key="linearGradientforButton">
<GradientStop Color="Blue" Offset="0"/>
<GradientStop Color="White" Offset="0.5"/>
<GradientStop Color="Cyan" Offset="1"/>
</LinearGradientBrush>
<Style TargetType="Button" x:Key="ButtonStyle">
<Setter Property="Width" Value="150" />
<Setter Property="Height" Value="40" />
<Setter Property="HorizontalAlignment" Value="Center"
/>
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="Margin" Value="10" />
</Style>
</ResourceDictionary>
MainWindow.Xaml
<Window x:Class="WpfApplication1.WPFResourcesDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WPF Resources"
Height="100" Width="300">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyResourceDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Button Name="MyButton"
Content="Click Me!"
Background="{StaticResource
linearGradientforButton}"
Style="{StaticResource ButtonStyle}" />
</Grid>
</Window>
The output of
this example is same as above two examples. In this example resources are
placed inside separate ResourceDictionary file and in MainWindow resource dictionary merged in Window.Resources element.
Accessing Resources from code -
WPF resources can also be created or
accessed using code. Inside code we need to find resource by key name using
TryFindResoruce Method or FindResource method. Both methods used
to find resources from resource dictionary the only difference is FindResource
method will throw an exception if resource not found while TryFindResource
Method will return null. Let’s have a look on below code.
private void
MyButton_Click(object sender, RoutedEventArgs e)
{
MyButton.Background = (Brush)TryFindResource("linearGradientforButton");
}
In above code
snippet, TryFindResource method will try to find “linearGradientforButton”
resource from dictionary if found assign to background property and if not found then
assign null to background property.
Hope you
liked this article on WPF Resources. Please feel free to write
feedback/comments in comment section below.
See also –