👉 How To Use Resources
You will often need to standardise graphical fundamentals such as (but not limited to) brushes and colors in your applications. You can define these as resources at various levels in your Avalonia UI application, as well as in files that can be included as required.
Resources are always defined inside a resource dictionary. This means that each resource has a key attribute.
The level of a resource dictionary defines the scope of the resources in it: resources are available in the file where they are defined, and below. So you can tailor the scope of resources by choosing where to locate a resource dictionary.
Declaring Resources
For example, you may want brush colors to be standardized across the whole application. In this case you can declare a resource dictionary in the application XAML App.axaml file, like this
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyApp.App">
<Application.Resources>
<SolidColorBrush x:Key="Warning">Yellow</SolidColorBrush>
</Application.Resources>
</Application>
Alternatively, you may want a set of resources to apply only to a specific window or user control. In this case you will define a resource dictionary in the window or user control file. For example:
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyApp.MyUserControl">
<UserControl.Resources>
<SolidColorBrush x:Key="Warning">LightYellow</SolidColorBrush>
</UserControl.Resources>
</UserControl>
In fact you can define resources at control level if required:
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyApp.MainWindow">
<StackPanel>
<StackPanel.Resources>
<SolidColorBrush x:Key="Warning">PaleGoldenRod</SolidColorBrush>
</StackPanel.Resources>
</StackPanel>
</Window>
You can also declare resources to be specific to a style.
<Style Selector="TextBlock.warning">
<Style.Resources>
<SolidColorBrush x:Key="Warning">Yellow</SolidColorBrush>
</Style.Resources>
<Setter ... />
</Style>
Keep in mind, this resource is not visible outside of the this specific style block, meaning it won't make every TextBlock with a "warning" class aware of this resource outside of the Style block.
It is also possible to define resources for specific theme variants: Dark, Light or custom. From the example below, BackgroundBrush
and ForegroundBrush
will have different values depending on the current theme variant set by the system or application. For more information about theme variants please read Theme Variants page.
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key='Light'>
<SolidColorBrush x:Key='BackgroundBrush'>White</SolidColorBrush>
<SolidColorBrush x:Key='ForegroundBrush'>Black</SolidColorBrush>
</ResourceDictionary>
<ResourceDictionary x:Key='Dark'>
<SolidColorBrush x:Key='BackgroundBrush'>Black</SolidColorBrush>
<SolidColorBrush x:Key='ForegroundBrush'>White</SolidColorBrush>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
Resource Dictionary Files
You can improve the organisation of your Avalonia UI application project by defining resource dictionaries in their own files. This makes resource definitions easy to locate and maintain.
Resources located in a resource dictionary file are accessible to the entire application.
To add a resource dictionary file, follow this procedure:
- Right-click your project at the location where you want the new file created.
- Click Add, then New Item.
- Click Avalonia in the list on the left:
- Click Resource Dictionary (Avalonia).
- Type the file name you want to use.
- Click Add.
You can now add the resources you want to define in the position indicated. It looks like this:
<ResourceDictionary xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Add Resources Here -->
</ResourceDictionary>
Using Resources
You can use a resource from a resources dictionary that is in scope using the {DynamicResource}
mark-up extension.
For example, to use a resource directly on the background attribute of a border element, use the following XAML :
<Border Background="{DynamicResource Warning}">
Look out!
</Border>
Static Resource
Alternatively you can choose to use the StaticResource
mark-up extension. For example:
<Border Background="{StaticResource Warning}">
Look out!
</Border>
A static resource is different in that it will not respond to changes in the resource made in code (at runtime). Once loaded a static cannot be altered.
The benefit of using a static resource is that it has less work to do so it will be slightly faster to load, and it uses slightly less memory.
Resource Priority
Avalonia UI resolves what resource to use by searching upwards in the logical control tree from the level of a DynamicResource
or StaticResource
mark-up, looking for the resource key.
This means that resources with the same key have priority based on their proximity to the resource mark-up being resolved. Resource definitions further up the logical control tree are therefore effectively 'overridden' by those that are closer. For example, consider this XAML:
<UserControl ... >
<UserControl.Resources>
<SolidColorBrush x:Key="Warning">Yellow</SolidColorBrush>
</UserControl.Resources>
<StackPanel>
<StackPanel.Resources>
<SolidColorBrush x:Key="Warning">Orange</SolidColorBrush>
</StackPanel.Resources>
<Border Background="{DynamicResource Warning}">
Look out!
</Border>
</StackPanel>
</UserControl>
Here the border control is using the resource with the key 'Warning'. This is defined twice - once at the level of the enclosing stack panel, and again at user control level. Avalonia UI will determine that the border background should be be orange because its parent stack panel is first in a search upwards in the logical control tree from the border itself.
Include and Merge Resources
Resources can be included from a resource dictionary file, and merged with the resources defined in another file (even if there are not any).
This means that you can implement styles in one file, and use resources defined in another. This keeps your styling consistent, and your application solution well organised and easy to maintain.
To include the resources dictionary from a file in a styles file, add the following XAML:
<Styles.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceInclude Source="/Assets/AppResources.axaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Styles.Resources>
In the above example, the resources file AppResources.axaml
is located in the /Assets
project folder. You can then define the styles using the resources, for example:
<Style Selector="Button.btn-info">
<Setter Property="Background" Value="{StaticResource InfoColor}"/>
</Style>
Where the resource InfoColor
is defined as a SolidColorBrush
in the imported file.
Note that the resource has been referenced using StaticResource
because it must not change - the requirement here is to keep the styling consistent.