问题
I am working with a very large Silverlight 5 application that needs to implement theming. Unfortunately I can't use the C1 (Component One) or Silverlight Toolkit theme mechanisms due to the enormity of xaml and code changes I would have to implement. I am forced to do something a bit out of the box.
As a starting point I created a demo project by referencing a post on Stack Overflow Using Mef to Import a WPF DataTemplate written by @Scott Whitlock. The post described how to dynamically load a Silverlight/WPF resource dictionary and add it to the App.Current.Resources.MergedDictionaries
collection within the Silverlight/WPF application.
I created 4 projects. The first being the Silverlight 5 application itself, the second, third, and forth are silverlight class libraries for defining all the theme particulars. Each class library has an entry point which is a derived type of ResourceDictionary
.
On AppStart event, the application loads the default theme class library, which is essentially a blank slate with all default styles defined in Silverlight. By loading I mean the the DefaultTheme
resource dictionary defined within the class library is added to the App.Current.Resources.MergedDictionaries
collection.
When the user selects another theme from a combo box within the app, the code removes the existing default theme and adds the blue or red, or whatever other theme's entry point resource dictionary to the App.Current.Resources.MergedDictionaries
collection.
However, even though no errors have been thrown when this action occurs, the styles themselves are never re-applied. I have verified that each theme has the same style keys across the board.
Any ideas on how to force the App.Current.RootVisual
re-apply the styles from the newly added resource dictionary after a "theme switch" ?
Thanks,
回答1:
Try searching for the current ResourceDictionary first and removing it before adding the new ResourceDictionary.
string themeName = "White";
string oldThemeName = "Black";
string oldResourcePathString = String.Format("/Library.Name;component/Themes/{0}Theme.xaml", oldThemeName);
StreamResourceInfo sriOldTheme = Application.GetResourceStream(new Uri(oldResourcePathString, UriKind.Relative));
if (sriOldTheme != null)
{
StreamReader sr = new StreamReader(sriOldTheme.Stream);
object resourceObject = XamlReader.Load(sr.ReadToEnd());
ResourceDictionary resource = resourceObject as ResourceDictionary;
if (resource != null)
{
Application.Current.Resources.MergedDictionaries.Remove(resource);
}
}
string resourcePathString = String.Format("/Library.Name;component/Themes/{0}Theme.xaml", themeName);
StreamResourceInfo sriTheme = Application.GetResourceStream(new Uri(resourcePathString, UriKind.Relative));
if (sriTheme != null)
{
StreamReader sr = new StreamReader(sriTheme.Stream);
object resourceObject = XamlReader.Load(sr.ReadToEnd());
ResourceDictionary resource = resourceObject as ResourceDictionary;
if (resource != null)
{
Application.Current.Resources.MergedDictionaries.Add(resource);
}
}
I never tested the code, so check for typos, but this should work whether you set the ResourceDictionary in App.xaml or programatically from MainPage.xaml.cs
来源:https://stackoverflow.com/questions/19390286/how-to-apply-styles-in-a-resource-dictionary-that-is-programmatically-added-to-t