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

时间:2022-12-31 14:12:14

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.

我正在处理一个需要实现主题的大型Silverlight 5应用程序。不幸的是,我不能使用C1(组件1)或Silverlight Toolkit主题机制,因为xaml的庞大性和必须实现的代码更改。我*去做一些开箱即用的事情。

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.

作为起点,我创建了一个演示项目,通过引用一个关于栈溢出的帖子,使用Mef导入@Scott Whitlock编写的WPF DataTemplate。本文描述了如何动态加载Silverlight/WPF资源字典并将其添加到App.Current.Resources。银光/WPF应用程序中的mergeddictionary集合。

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.

我创建了4个项目。第一个是Silverlight 5应用程序本身,第二个、第三个和第四个是定义所有主题细节的Silverlight类库。每个类库都有一个入口点,它是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.

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

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.

当用户从应用程序中的组合框中选择另一个主题时,该代码将删除现有的缺省主题,并将蓝色或红色或其他主题的入口点资源字典添加到app . current. resources中。MergedDictionaries集合。

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" ?

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

Thanks,

谢谢,

1 个解决方案

#1


0  

Try searching for the current ResourceDictionary first and removing it before adding the new ResourceDictionary.

尝试先搜索当前的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);
  }
}

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

我从来没有测试过这些代码,所以请检查输入错误,但是无论您是在App.xaml中设置ResourceDictionary,还是在mainpage .xam .cs中以编程方式设置ResourceDictionary,都应该这样做

#1


0  

Try searching for the current ResourceDictionary first and removing it before adding the new ResourceDictionary.

尝试先搜索当前的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);
  }
}

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

我从来没有测试过这些代码,所以请检查输入错误,但是无论您是在App.xaml中设置ResourceDictionary,还是在mainpage .xam .cs中以编程方式设置ResourceDictionary,都应该这样做