Resource dictionaries in WPF are not shared, unless they are part of App.xaml
. That is, if you have a user control that loads (and uses) some resource dictionary, new instance of the dictionary will be loaded for each instance of the user control. This can (and does) lead to increased loading time and memory footprint.
I wrote a test application that demonstrates the problem. Source code Visio diagrams
Main window has four user control objects: two of type UserControl1
(red) and two of type UserControl2
(yellow). I defined a class named BigFatObject
that allocates 200MB of memory. As instances of the class are created, they get sequential numbers: #1, #2, etc. Each user control refers to one instance of BigFatObject
from App.xaml
and to another instance from Dictionary1.xaml
. You can see that instance #1 from App.xaml
is shared by all controls, but each control has its own instance from Dictionary1.xaml
(#2, #3, #4, and #5 respectively).
As a result, the application has 5 (five) 200MB objects, and its memory footprint is over 1GB in size. In our production code private dictionaries contained not one big object, but lots of small objects (brushes, colors, styles, etc.). This affected not only memory footprint, but also the startup time. Each time a user control was created, the dictionary had to be processed and all objects in it re-created.
Here’s how I use a resource dictionary in my user controls:
<UserControl ...> <UserControl.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Dictionary1.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </UserControl.Resources> </UserControl>
Here’s the relationship between XAML files in the application:
And here’s the object graph:
You can easily observe the duplication.
The solution to this problem is to put shared resource in App.xaml
or include your dictionary from App.xaml
. If you don’t have control over App.xaml
, manually load your shared resources in code as described in this StackOverflow article. If you continue to refer to shared resources from user controls, you will suffer from increased memory footprint and slow load times.
Permalink
Hello, this is a very interesting article, thank you for it!
What about controls inside ContentPresenter control? Can I force them to use resources from App.xaml?
Permalink
In theory, everything in your application should be able to use resources from
app.xaml
. I just verified that a control dynamically assigned to be a content of aContentControl
(that internally usesContentPresenter
) can use resources fromapp.xaml
. Do you have a specific example when that does not work?