【问题标题】:How to change ResourceDictionary Dynamically如何动态更改资源字典
【发布时间】:2022-05-17 18:52:05
【问题描述】:

我需要动态更改App.xaml 文件中的ResourceDictionary。我试过以下代码:

ResourceDictionary newRes = new ResourceDictionary();
newRes.Source = new Uri("/PsyboInventory;component/TitleBarResource.xaml", UriKind.RelativeOrAbsolute);
this.Resources.MergedDictionaries.Clear();
this.Resources.MergedDictionaries.Add(newRes);

没有错误,但主题没有改变

【问题讨论】:

    标签: c# wpf resourcedictionary


    【解决方案1】:

    在按钮点击你可以写这段代码

    var app = (App)Application.Current;
    app.ChangeTheme(new Uri("New Uri here"));
    

    更改主题:

    public partial class App : Application
        {
            public ResourceDictionary ThemeDictionary
            {
                // You could probably get it via its name with some query logic as well.
                get { return Resources.MergedDictionaries[0]; }
            }
        
            public void ChangeTheme(Uri uri)
            {
                ThemeDictionary.MergedDictionaries.Clear();
                ThemeDictionary.MergedDictionaries.Add(new ResourceDictionary() { Source = uri });
            } 
           
        }   
    
        <Application.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary x:Name="ThemeDictionary">
                        <ResourceDictionary.MergedDictionaries>
                            <ResourceDictionary Source="/Themes/ShinyRed.xaml"/>
                        </ResourceDictionary.MergedDictionaries>
                    </ResourceDictionary>
        </ResourceDictionary.MergedDictionaries>
    

    【讨论】:

      【解决方案2】:

      只是改变:

      newRes.Source = new Uri("/PsyboInventory;component/TitleBarResource.xaml", UriKind.RelativeOrAbsolute);
      

      收件人:

      newRes.Source = new Uri("TitleBarResource.xaml", UriKind.Relative);
      

      如果您想将其从 Button_OnClick 事件更改,则应将应用程序中使用的所有 StaticResource 更改为 DynamicResource,例如更改以下内容:

      <Button Style="{StaticResource buttonStyle}" >Click Me!</Button>
      

      到这里:

      <Button Style="{DynamicResource buttonStyle}" >Click Me!</Button>
      

      【讨论】:

      • 我需要从按钮中的表单更改它
      • @ShahidNeermunda...如果您想在按钮中使用,请将应用程序中使用的所有StaticResource 更改为DynamicResource
      【解决方案3】:

      这是我用来处理这些情况的类。您可以在我的GitHub Demo 中找到完整的演示。

      namespace JamSoft.CALDemo.Modules.SkinManager
      {
          using System;
          using System.Collections.Generic;
          using System.Collections.ObjectModel;
          using System.Linq;
          using System.Windows;
      
          using JamSoft.CALDemo.Modules.SkinManager.Core;
          using JamSoft.CALDemo.Modules.SkinManager.Core.Exceptions;
      
          /// <summary>
          /// The skin manager class
          /// </summary>
          public class SkinManager : DependencyObject, ISkinManager
          {
              /// <summary>
              /// The current skin property
              /// </summary>
              public static readonly DependencyProperty CurrentSkinProperty = DependencyProperty.Register(
                  "CurrentSkin", 
                  typeof(Skin), 
                  typeof(SkinManager), 
                  new UIPropertyMetadata(Skin.Null, OnCurrentSkinChanged, OnCoerceSkinValue));
      
              /// <summary>The default skin name</summary>
              private const string DefaultSkinName = "Default";
      
              /// <summary>The _skin finder</summary>
              private readonly SkinsFinder _skinFinder = new SkinsFinder();
      
              /// <summary>The _skins</summary>
              private List<Skin> _skins = new List<Skin>();
      
              /// <summary>
              /// Initializes a new instance of the <see cref="SkinManager"/> class.
              /// </summary>
              public SkinManager()
              {
                  Initialize();
              }
      
              /// <summary>Gets the skins.</summary>
              /// <value>The skins.</value>
              public ObservableCollection<Skin> Skins
              {
                  get
                  {
                      return new ObservableCollection<Skin>(_skins);
                  }
              }
      
              /// <summary>Gets or sets the current skin.</summary>
              /// <value>The current skin.</value>
              public Skin CurrentSkin
              {
                  get
                  {
                      return (Skin)GetValue(CurrentSkinProperty);
                  }
      
                  set
                  {
                      SetValue(CurrentSkinProperty, value);
                  }
              }
      
              /// <summary>Loads the specified skin or the default if specified skin isn't found.</summary>
              /// <param name="skinName">Name of the skin.</param>
              public void LoadSkin(string skinName)
              {
                  var skin = _skins.FirstOrDefault(x => x.Name.Equals(skinName)) ?? _skins.FirstOrDefault(x => x.Name == DefaultSkinName);
                  CurrentSkin = skin;
              }
      
              /// <summary>
              /// Called when [coerce skin value].
              /// </summary>
              /// <param name="d">The <paramref name="d"/>.</param>
              /// <param name="baseValue">The base value.</param>
              /// <returns>the coerced skin <see langword="object"/></returns>
              private static object OnCoerceSkinValue(DependencyObject d, object baseValue)
              {
                  if (baseValue == null)
                  {
                      return Skin.Null;
                  }
      
                  return baseValue;
              }
      
              /// <summary>
              /// Called when [current skin changed].
              /// </summary>
              /// <param name="d">The <paramref name="d"/>.</param>
              /// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
              private static void OnCurrentSkinChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
              {
                  try
                  {
                      Skin oldSkin = e.OldValue as Skin;
                      oldSkin.Unload();
                      Skin newSkin = e.NewValue as Skin;
                      newSkin.Load();
                  }
                  catch (SkinException ex)
                  {
                      Console.WriteLine(ex);
                  }
              }
      
              /// <summary>Initializes <c>this</c> instance.</summary>
              private void Initialize()
              {
                  _skinFinder.Initialize();
                  _skins = _skinFinder.SkinsList;
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        我通过在所有Window的构造函数中的InitializeComponent()方法上方添加以下代码解决了上述问题。

        ResourceDictionary newRes = new ResourceDictionary();
        newRes.Source = new Uri("/PsyboInventory;component/TitleBarResource.xaml",UriKind.RelativeOrAbsolute);
        this.Resources.MergedDictionaries.Clear();
        this.Resources.MergedDictionaries.Add(newRes);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-08-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多