如何在以编程方式添加到App.Current.Resources.MergedDictionaries集合的资源字典中应用样式?

时间:2013-10-15 20:20:04

标签: wpf silverlight mef silverlight-5.0

我正在使用需要实现主题的非常大的Silverlight 5应用程序。不幸的是,我不能使用C1(组件一)或Silverlight Toolkit主题机制,因为我需要实现xaml和代码更改的巨大。我被迫做了一些开箱即用的事情。

作为起点,我通过引用@Scott Whitlock编写的Stack Overflow Using Mef to Import a WPF DataTemplate上的帖子创建了一个演示项目。该帖子描述了如何动态加载Silverlight / WPF资源字典并将其添加到Silverlight / WPF应用程序中的App.Current.Resources.MergedDictionaries集合。

我创建了4个项目。第一个是Silverlight 5应用程序本身,第二个,第三个和第三个是用于定义所有主题细节的silverlight类库。每个类库都有一个入口点,它是ResourceDictionary的派生类型。

在AppStart事件中,应用程序加载默认主题类库,该库本质上是一个空白平板,其中包含Silverlight中定义的所有默认样式。通过加载,我的意思是将类库中定义的DefaultTheme资源字典添加到App.Current.Resources.MergedDictionaries集合中。

当用户从应用程序中的组合框中选择另一个主题时,代码将删除现有的默认主题,并将蓝色或红色或其他任何主题的入口点资源字典添加到App.Current.Resources.MergedDictionaries集合。

但是,即使发生此操作时未引发任何错误,也不会重新应用样式本身。我已经确认每个主题都具有相同的样式键。

有关如何在“主题切换”后强制App.Current.RootVisual重新应用新添加的资源字典中的样式的任何想法?

谢谢,

1 个答案:

答案 0 :(得分:0)

首先尝试搜索当前的ResourceDictionary并在添加新的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);
  }
}

我从未测试过代码,因此请检查拼写错误,但无论您是在App.xaml中设置ResourceDictionary还是从MainPage.xaml.cs以编程方式设置它都应该有效