首页 文章

WPF Skinning具有不同的系统主题

提问于
浏览
0

我们的 WPF 应用程序有几个UI皮肤,可以在运行时切换,并应用于特定的框架元素及其子元素 . Skin 是编译的xaml资源字典,存储在 Theming dll中,Skinning是通过使用自定义 SkinManager 类和附加依赖项属性 Skin 实现的,实际上是通过将skin的资源字典添加到目标FrameworkElement.Resources.MergedDictionaries来更改外观 . 皮肤字典包含具有TargetType =“SomeType " and BasedOn=" {StaticResource {x:Type SomeType}}”的样式,因此基于WPF系统主题的隐式样式将此样式应用于SomeType的所有框架元素 . 这种方法很有效,但是当我们尝试将 Theming 引入我们的应用程序时,我们遇到了问题 .

Theme 我们的定义是一个自定义皮肤,适用于整个应用程序特定的系统主题(Classic,Luna,Royale,Aero,Aero2(又名Metro)) . 它是通过将相应的资源文件从系统dll(Aero.normalcolor.xaml,来自PresentationFramework.Aero for Aero theme)加载到Application.Resources.MergedDictionaries来实现的 . 如果我们为此resourcedictionary添加外观,则会忽略-it,因此外观将应用于每个活动窗口 . 这也很好,但是我们遇到了在运行时切换主题的困难:
如果主题基于相同的系统主题 - 比没有问题,否则我们会产生令人讨厌和不受欢迎的行为:带有应用皮肤的框架元素不会改变它们通过隐式样式引入的外观(例如按钮不会在royale主题时使用chrome和padding此外,如果我们尝试为皮肤和主题存储资源的独特实例,那么当具有相同皮肤的主题在视觉上合并到同一主题中时,我们就会遇到这样的情况:如果我们尝试应用这些主题,那么应用的那个首先应用每次(例如,如果theme1 = royale blueskin,theme2 = aero blueskin,那么如果首先应用theme1,那么theme1和theme2的应用在两种情况下都应用"royale"外观)
有没有可能的方法来克服这些问题并在运行时更改WPF隐式样式?或者我们没有注意到有关资源字典的WPF机制的一些重要细节?

2 回答

  • 0

    如果我理解你正确应用第一个“皮肤”的问题,即使你设置另一个,请先尝试清除合并的资源字典...

    这里有很多与运行时加载资源相关的主题,例如switching wpf resource dictionaries at runtime

    这表现了:

    ResourceDictionary dic = (ResourceDictionary)XamlReader.Load(fs);
    Application.Current.Resources.MergedDictionaries.Clear();
    Application.Current.Resources.MergedDictionaries.Add(dic);
    
  • 0

    通过改变WPF Internals的实际系统主题并删除隐式样式的BasedOn声明,我们成功地使用MS.Win32.UXThemeWrapper类以这里使用的方式应用特定的系统主题https://github.com/danielmoore/SystemThemeChange/blob/master/ThemeHelper.cs .

相关问题