Reputation: 19413
The WPF documentation on MergedDictionaries
suggests that if you load two ResourceDictionaries
in XAML, the second loaded one will be able to reference the first. The Windows Phone documentation on MergedDictionaries
does not explicity state this but I assume the same rules apply. However the following does not work in my Windows Phone App.xaml,
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="View/ThemeDictionaries/LightThemeResourceDictionary.xaml"/>
<ResourceDictionary Source="View/ThemeDictionaries/MainResourceDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
The debug says the MainResourceDictionary line cannot reference SubTitleTextColor
which is defined in LightThemeResourceDictionary - I have checked the spelling of the reference.
Is this type of loading not possible in Windows Phone? How do I work around it?
Upvotes: 1
Views: 543
Reputation: 19413
Thanks to Abe for the help, although in the end I went with a 'resolver' class that is included as a merged dictionary and resolves to the appropriate theme dictionary. The reasons are beyond the scope of he original question:
App.xaml.cs
without later having to overwrite the resources programatically based on user choice (before you would have to merge in a default theme, say Light at initialisation, and if the user had selected Dark then merge in the Dark theme later)The code is based on an idea by this blogger.
ThemeResourceDictionaryResolver.cs
using System;
using System.IO;
using System.Windows;
using System.Windows.Markup;
using System.Windows.Resources;
using System.IO.IsolatedStorage;
namespace YourAppName.View
{
public enum ApplicationTheme
{
Dark,
Light
}
public class ThemeResourceDictionaryResolver : ResourceDictionary
{
public ThemeResourceDictionaryResolver() : base()
{
ApplicationTheme theme;
if (System.ComponentModel.DesignerProperties.IsInDesignTool)
{
// Set here which dictionary you want to be loaded in Blend
theme = ApplicationTheme.Light;
}
else
{
ApplicationTheme theme;
if (!IsolatedStorage.ApplicationSettings.TryGetValue("ApplicationTheme", out theme))
{
// The 'standard' way to get the global phone theme
Visibility darkBGVisibility = (Visibility)Application.Current.Resources["PhoneDarkThemeVisibility"];
theme = (darkBGVisibility == Visibility.Visible) ? ApplicationTheme.Dark : ApplicationTheme.Light;
}
}
// Change the URI string as appropriate - this way refers to the Dictionaries
// which are set to 'Build: Page'. I couldn't get to work when set to Build as
// Content and using the simpler URI scheme.
Uri uri = new Uri(string.Format("YouAppName;component/View/Themes/{0}ThemeResourceDictionary.xaml", theme), UriKind.RelativeOrAbsolute);
ResourceDictionary res = this.LoadXaml<ResourceDictionary>(uri);
this.MergedDictionaries.Add(res);
}
// For some reason a simple ResourceDictionary() { Source = uri }; does not work,
// need to use this instead
T LoadXaml<T>(Uri uri)
{
StreamResourceInfo info = Application.GetResourceStream(uri);
if (info != null)
{
using (StreamReader reader = new StreamReader(info.Stream))
{
return (T)XamlReader.Load(reader.ReadToEnd());
}
}
return default(T);
}
}
}
MainResourceDictionary.xaml
...
<ResourceDictionary.MergedDictionaries>
<views:ThemeResourceDictionaryResolver />
</ResourceDictionary.MergedDictionaries>
<!-- StaticResources that refer to the theme StaticResources can go here -->
...
App.xaml
...
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="View/Themes/MainResourceDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
...
Upvotes: 1
Reputation: 30498
Based on the Silverlight Resources documentation (much more applicable than the WPF ones), this scenario won't work. There are 2 ways to get around this:
List<ResourceDictionary>
that will manually merge them into one giant ResourceDictionary
and set the application's resources to it.Upvotes: 1