Reputation: 975
I have found this post about improving performance of ResourceDictionaries
on the web, but the problem is that it's pretty old (2011). I was thinking about implementing something like this, but I'm wondering if Microsoft has not fixed this in the last releases of .NET Framework. I have few questions regarding this topic, which, I hope someone here can give an answer to:
ResourceDictionaries
by making multiple instances of them, one for every time they are assigned to a control?"CustomButtonStyle"
in my ResourceDictionary
called "ButtonStyles"
in assembly called "StylesAssembly"
, which is then referenced in App.xaml
of an application, that has 20 Buttons
with CustomButtonStyle
assigned to them? "ButtonStyles"
ResourceDictionary
?Upvotes: 5
Views: 1774
Reputation: 21
I have recently been working on an alternative solution with a friend and I wanted to share it. The goal is to be able to use ResourceDictionaries anywhere and merge them in whatever way necessary, but still have them instantiated only once and without breaking the VS designer and Blend etc.
Instructions:
1. Use merged ResourceDictionaries in xaml as you see fit.
2. Reference nuget packages Sundew.Xaml.Optimizations and Sundew.Xaml.Optimizer
3. Add a sxo-settings.json in the root of your project and enable the ResourceDictionaryCachingOptimizer
4. Build
The build will use a caching/shared ResourceDictionary, but designer will also work because they only see the normal ResourceDictionary.
For more details see: https://github.com/hugener/Sundew.Xaml.Optimizations
And a sample: https://github.com/hugener/Sundew.Xaml.Optimizer.Sample
Upvotes: 1
Reputation: 975
Thanks @mm8 for posting your answer. It's 100% correct, I just want to post my own answer, because I found out something interesting, that can be useful for someone else.
The answer is: ResourceDictionary instance will be created just once if referenced in the application (no matter many controls uses its styles), BUT it will be instantiated again for every time it is referenced in another ResourceDictionary that is also used in the application.
So to give you example of this case let's say we have the following structure:
- StylesAssembly.dll
- ButtonResourceDictionary.xaml
- CustomButtonResourceDictionary.xaml
- Application.exe
- App.xaml
- MainWindow.xaml
ButtonResourceDictionary.xaml has the following code:
<Style x:Key="DefaultButtonStyle" TargetType="{x:Type Button}">
<!-- Some setters -->
</Style>
CustomButtonResourceDictionary.xaml has the following code, which uses ButtonResourceDictionary.xaml
:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ButtonResourceDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style x:Key="CustomButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource DefaultButtonStyle}">
<!-- Some setters -->
</Style>
Application.exe
has a reference to StylesAssembly.dll
and there is a following code in the App.xaml:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/StylesAssembly;component/ButtonResourceDictionary.xaml" />
<ResourceDictionary Source="pack://application:,,,/StylesAssembly;component/CustomButtonResourceDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Now if our MainWindow.xaml has something like this in it, the ButtonResourceDictionary.xaml
will have only one instance:
<StackPanel>
<Button Style="{StaticResource DefaultButtonStyle}" />
<Button Style="{StaticResource DefaultButtonStyle}" />
<Button Style="{StaticResource DefaultButtonStyle}" />
<Button Style="{StaticResource DefaultButtonStyle}" />
<Button Style="{StaticResource DefaultButtonStyle}" />
</StackPanel>
but if our MainWindow.xaml has something like this in it, the CustomButtonResourceDictionary.xaml
will have one instance, but the ButtonResourceDictionary.xaml
will have two instances:
<StackPanel>
<Button Style="{StaticResource DefaultButtonStyle}" />
<Button Style="{StaticResource DefaultButtonStyle}" />
<Button Style="{StaticResource CustomButtonStyle}" />
<Button Style="{StaticResource CustomButtonStyle}" />
<Button Style="{StaticResource CustomButtonStyle}" />
</StackPanel>
It happens because first two Buttons
use style DefaultButtonStyle
from ButtonResourceDictionary.xaml
, but another three Buttons
use style CustomButtonStyle
which comes from CustomButtonResourceDictionary.xaml
, which merges ButtonResourceDictionary.xaml
in its code.
Upvotes: 4
Reputation: 169200
Do I understand it correctly, that in the case above, there will be 20 instances of "ButtonStyles"
ResourceDictionary
?
No. Only one.
Is it even an issue when I have for example style "CustomButtonStyle" in my
ResourceDictionary
called "ButtonStyles" in assembly called "StylesAssembly", which is then referenced inApp.xaml
of an application, that has 20 Buttons with CustomButtonStyle assigned to them?
If you merge the ResourceDictionary
into your App.xaml
and create 20 Button
elements across the views in your application, there will still be only one instance of the ResourceDictionary
class created.
You can confirm this yourself by adding a code-behind class to the ResourceDictionary
:
Is it possible to set code behind a resource dictionary in WPF for event handling?
...and put a breakpoint in the constructor.
There will also be only one instance of the Style
defined in the ResourceDictionary
created.
Upvotes: 3