I experienced a problem, when I am trying to merge resource dictionaries at app-level. As soon as I changed the target framework from 3.5 to 4.0 they don't get loaded anymore. It seems as if they have changed something in the behavior of MergedResourceDictionaries in .NET 4.0.
I found a way how to fix this problem. Just add a dummy default style in the resource dictionary where you merge all resources together. See the following example:
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation",
"WPFTutorial.Utils")]
/// <summary>
/// The shared resource dictionary is a specialized resource dictionary
/// that loads it content only once. If a second instance with the same source
/// is created, it only merges the resources from the cache.
/// </summary>
public class SharedResourceDictionary : ResourceDictionary
{
/// <summary>
/// Internal cache of loaded dictionaries
/// </summary>
public static Dictionary<Uri, ResourceDictionary> _sharedDictionaries =
new Dictionary<Uri, ResourceDictionary>();
/// <summary>
/// Local member of the source uri
/// </summary>
private Uri _sourceUri;
/// <summary>
/// Gets or sets the uniform resource identifier (URI) to load resources from.
/// </summary>
public new Uri Source
{
get { return _sourceUri; }
set
{
_sourceUri = value;
if (!_sharedDictionaries.ContainsKey(value))
{
// If the dictionary is not yet loaded, load it by setting
// the source of the base class
base.Source = value;
// add it to the cache
_sharedDictionaries.Add(value, this);
}
else
{
// If the dictionary is already loaded, get it from the cache
MergedDictionaries.Add(_sharedDictionaries[value]);
}
}
}
}
|
AVEbrahimi | |
|
Commented on 14.May 2009 |
Seems great, I'll check it and post results here.
I've very long startup time in my big WPF project...
|
|
|
|
Andrew | |
|
Commented on 28.May 2009 |
Looks nice, but is this SharedResourceDictionary Blend "friendly"?
|
|
|
|
Christian Moser | |
|
Commented on 28.May 2009 |
Hi Andrew,
No, unfortunately the current versions of Blend cannot deal with it :-( I am searching for another solution that is fast and also supported by Blend.
|
|
|
|
Andrew | |
|
Commented on 1.June 2009 |
Looks like I've found a solution which address the same issue as yours, but it is a Blend friendly - check it out http://www.drwpf.com/blog/Home/tabid/36/EntryID/10/Default.aspx - in section "Manage a Collection of Resource Dictionaries in Code and Merge them at the Element Level" there is class "SharedResources".
|
|
|
|
DJanjicek | |
|
Commented on 31.July 2009 |
Hi Andrew,
since totday I'm using MergedDictionaries in my Silverlight project and I'm facing huge performance problems. The app is consuming almost 1GB of memory after a few clicks. Your solution could help me out of this trouble but I have no idea how to implement your code and how to use it.
Could you help me with this?
|
|
|
|
Sergey | |
|
Commented on 10.August 2009 |
I agree with DJanjicek.
Andrew, could you share an example of using your class?
|
|
|
|
Cameron | |
|
Commented on 24.August 2009 |
Just be aware... we were using the SharedResourceDictionary in our project, until we found out that it was holding onto XAML pages that had been closed, and thus were not being garbage collected.
|
|
|
|
HDW | |
|
Commented on 31.October 2009 |
_sourceUri = new Uri(value.OriginalString); allows garbage collection.
Also wrapping access to _sharedDictionaries in lock (((ICollection)_sharedDictionaries).SyncRoot) and wrapping access to MergedDictionaries in lock (((ICollection)MergedDictionaries).SyncRoot) makes the class thread safe.
|
|
|
|
fmunkert | |
|
Commented on 9.November 2009 |
SharedResourceDictionary seems not be compatible with the {ThemeDictionary ...} markup extensions. An InvalidOperationException is thrown which states that ThemeDictionaryExtension can be used with ResourceDictionary only.
There might be other code in WPF which does not work if you derive from ResourceDictionary.
|
|
|
|
Lee Campbell | |
|
Commented on 12.May 2010 |
Thanks Christian,
FYI: I have added a colleagues expansion on the problem referencing this post on this site
http://leecampbell.blogspot.com/2010/05/mergeddictionaries-performance-problems.html
|
|
|
|
Mike | |
|
Commented on 2.July 2010 |
I'm having some issues with this solution in the designer. I am trying to use the designer in VS2010. Using this, I get an error when using the designer, and I can't get any code completion. Any ideas, if this works in the designer?
|
|
|
|
Fran Herrera | |
|
Commented on 31.August 2010 |
Same here. I'm receiving a NotSupportedException when using SharedResourceDictionary on design time. When running the app, everything seems to work. VS2010Express.
|
|
|
|
jep | |
|
Commented on 16.November 2010 |
The code mentioned above to fix garbage collection throws exceptions:
_sourceUri = new Uri(value.OriginalString); allows garbage collection.
Any solution to this?
|
|
|
|
shemesh | |
|
Commented on 22.November 2010 |
i m working with Silverlight 4.
1) isn't this behavior (of making a new instance for each control reference) is a memory leak? shouldn't this be addressed by Microsoft?
2)could you post a code that allows GC and thread safe?
|
|
|
|
EinMitleser | |
|
Commented on 17.December 2010 |
If you want use the MergedDictionary and working Designer, just implement this :
public bool IsInDesignMode
{
get
{
return
(bool)
DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty,
typeof(DependencyObject)).Metadata.DefaultValue;
}
}
|
|
|
|
EinMitleser | |
|
Commented on 17.December 2010 |
Hello,
if you want to use this class in your project without loosing the designer, just impemelent this static prop into the class:
private static bool IsInDesignMode
{
get
{
return (bool) DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty,
typeof(DependencyObject)).Metadata.DefaultValue;
}
}
--- thats the new getter:
if (IsInDesignMode)
return base.Source;
return _sourceUri
And this put in front of the old setter-code :
if (IsInDesignMode)
{
base.Source = value;
return;
}
The problem is the memory at runtime(yes ms just cookin with water, like all others too/do)...and thanks to mr. moser for his little work...
|
|
|
|
Ups | |
|
Commented on 17.December 2010 |
I forgott to write the try catch sourrund the base.Source=value
|
|
|
|
Arun | |
|
Commented on 14.January 2011 |
ya its very useful for us.Its a great one for beginners.
|
|
|
|
Mary Ellen | |
|
Commented on 19.January 2011 |
Does anyone have this working in Silverlight 4? I am getting an exception when it tries to do "MergedDictionaries.Add" --> InvalidOperationException: Element is already the child of another element.
Any help is appreciated.
|
|
|
|
Coop | |
|
Commented on 1.February 2011 |
I'm also trying to get this working in SL4. Anyone know of a good example?
|
|
|
|
bobs | |
|
Commented on 28.March 2011 |
nice article.... Thanks!!
|
|
|
|
David Compton | |
|
Commented on 1.April 2011 |
In order to overcome the designer issue I used a Powershell script in a Pre and Post Build event to change ResourceDictionary to SharedResourceDictionary at build time.
|
|
|
|
Kaushal | |
|
Commented on 25.May 2011 |
Hi Christian,
We are experiencing problem is display of context of ViewBox after installing .Net 4.0 framweowrk. Viewbox contains some chart or tabular data. Problem is that some text get invisible on randoam basis. Cant google any suitable solution.
Looking forward for your help.
|
|
|
|
Kaushal | |
|
Commented on 25.May 2011 |
Hi Christian,
We are experiencing problem is display of context of ViewBox after installing .Net 4.0 framweowrk. Viewbox contains some chart or tabular data. Problem is that some text get invisible on randoam basis. Cant google any suitable solution.
Looking forward for your help.
|
|
|
|
Vikas Dangwal | |
|
Commented on 3.June 2011 |
Hi Christian, Its really a good article. But when i am planning to use it, it shows me an compilation error state Error 13 The tag 'SharedResourceDictionary' does not exist in XML namespace '[My Name Space]'. Line 6 Position 10. [somefile.xaml] 6 10[ ProjectName]
Could you please tell me if i am missing something. I just created same class suggested by you.
|
|
|