【问题标题】:Changing Theme in Windows 10 UWP App Programmatically以编程方式更改 Windows 10 UWP 应用程序中的主题
【发布时间】:2016-04-05 22:10:50
【问题描述】:

我可以使用 this.RequestedTheme = ElementTheme.Dark; 更改主题 但是我需要的是整个应用程序级别,因为这只是将当前页面的主题更改为黑暗。

每当我尝试这个App.Current.RequestedTheme = ApplicationTheme.Dark; 我总是收到这个错误

UWPApp.exe 中出现“System.NotSupportedException”类型的异常,但未在用户代码中处理

有没有一种方法可以将整个应用程序主题从浅色更改为深色,反之亦然?

我正在使用 VS2015

【问题讨论】:

  • Template10 模板已内置此功能。您可以使用它们或从中收集解决方案。

标签: c# windows-10 windows-10-mobile windows-10-universal


【解决方案1】:

更新了我最终决定的答案。

我使用了一个设置类,其中包含所有应用设置,包括要使用的主题。由于主题只能在启动时设置,我们需要确保设置它们。这是我使用的代码:

在 App.xaml.cs 文件中:

public App()
{
    //Load settings
    AppSettings.LoadSettings();
    this.RequestedTheme = AppSettings.SelectedTheme;

    this.InitializeComponent();
}

确保在 App.xaml 文件中删除此属性:

    RequestedTheme="Light"

如果它没有被移除,它总是默认点亮,无法改变它。

这样用户可以选择主题,它会在应用启动时被存储和使用。只需确保在应用初始化阶段加载并应用它即可。

【讨论】:

  • 您好,感谢您的建议,我可能会检查您的建议以制作更灵活的主题,而不是仅使用 Microsoft 提供的默认深色和浅色主题。但是,如果您可以提供指向教程或以某种方式可以让我了解更多信息的网站的直接链接,我将不胜感激。非常感谢!
  • 那么,是否需要重启应用才能使主题生效?
  • 是的,要让它立即发生,您需要在应用程序内创建一个主题,然后将它们应用到应用程序中的每个元素。
【解决方案2】:

我找到了另一个对我来说效果很好的解决方案。如果应用程序有一个加载页面的根框架(默认情况下是这种情况),我可以将该根框架的请求主题设置为所需的值,并且应用程序的主题得到更改无需重新启动。代码如下所示:

// Set theme for window root.
if (Window.Current.Content is FrameworkElement frameworkElement)
{
   frameworkElement.RequestedTheme = theme;
}

我从 Windows Template Studio GitHub 存储库 here 获得了那个 sn-p,所以这似乎是最好的方法。

【讨论】:

    【解决方案3】:

    应用程序的 RequestedTheme 只能在构造函数中更新。但是(如您所见),页面的 RequestedTheme 可以在运行时随时更新。

    我知道这真的很烦人,除了这个 MSDN 页面之外没有太多关于这种情况的信息:

    https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.application.requestedtheme?f=255&MSPPError=-2147217396

    主题只能在应用启动时设置,不能在运行时设置。在应用程序运行时尝试设置 RequestedTheme 会引发异常(Microsoft .NET 代码的 NotSupportedException)。如果您为用户提供选择作为应用 UI 一部分的主题的选项,则必须将设置保存在应用数据中并在应用重新启动时应用。

    应该有解决方法,但它们会很愚蠢。微软在他们自己的官方应用程序中这样做,比如 Groove...

    我的解决方案是在元素级别进行主题更新,而不是应用程序级别。

    1. 创建自己的 BasePage(继承自 Page)
    2. 将您的设置保存在静态类下,并创建一个事件以持续跟踪模型更改。
    3. 在 BasePage 的构造函数中侦听此事件并在发生时应用更改。

    我现在无法提供代码示例(因为我今天很忙),但恕我直言,这是迄今为止最有效的方式。

    【讨论】:

    • 您好,感谢您的回答,我现在要做的是保存新主题,但需要重新启动应用程序才能生效。
    【解决方案4】:

    我发现axnull 的回答最有帮助,因为它允许在应用程序运行时设置主题。经过一个下午的工作后,我能够即时设置应用程序的主题并将其保存在内存中以供下次启动,通过ToggleButton 为用户提供控制权。

    首先,我创建了一个带有Theme 属性的设置类,它会自动存储当前设置:

    AppSettings.cs

    class AppSettings
    {
       public const ElementTheme DEFAULTTHEME = ElementTheme.Light;
       public const ElementTheme NONDEFLTHEME = ElementTheme.Dark;
    
       const string KEY_THEME = "appColourMode";
       static ApplicationDataContainer LOCALSETTINGS = ApplicationData.Current.LocalSettings;
    
       /// <summary>
       /// Gets or sets the current app colour setting from memory (light or dark mode).
       /// </summary>
       public static ElementTheme Theme {
          get {
             // Never set: default theme
             if (LOCALSETTINGS.Values[KEY_THEME] == null)
             {
                LOCALSETTINGS.Values[KEY_THEME] = (int)DEFAULTTHEME;
                return DEFAULTTHEME;
             }
             // Previously set to default theme
             else if ((int)LOCALSETTINGS.Values[KEY_THEME] == (int)DEFAULTTHEME)
                return DEFAULTTHEME;
             // Previously set to non-default theme
             else
                return NONDEFLTHEME;
          }
          set {
             // Error check
             if (value == ElementTheme.Default)
                throw new System.Exception("Only set the theme to light or dark mode!");
             // Never set
             else if (LOCALSETTINGS.Values[KEY_THEME] == null)
                LOCALSETTINGS.Values[KEY_THEME] = (int)value;
             // No change
             else if ((int)value == (int)LOCALSETTINGS.Values[KEY_THEME])
                return;
             // Change
             else
                LOCALSETTINGS.Values[KEY_THEME] = (int)value;
          }
       }
    }
    

    然后,在页面构造函数中,添加如下代码:

    MainPage.xaml.cs

      public MainPage()
      {
         this.InitializeComponent();
    
         // Set theme for window root
         FrameworkElement root = (FrameworkElement)Window.Current.Content;
         root.RequestedTheme = AppSettings.Theme;
         SetThemeToggle(AppSettings.Theme);
      }
    

    这会根据应用内存中的先前选择设置主题,并将切换设置为匹配。

    页面加载时会调用以下方法:

    MainPage.xaml.cs

      /// <summary>
      /// Set the theme toggle to the correct position (off for the default theme, and on for the non-default).
      /// </summary>
      private void SetThemeToggle(ElementTheme theme)
      {
         if (theme == AppSettings.DEFAULTTHEME)
            tglAppTheme.IsOn = false;
         else
            tglAppTheme.IsOn = true;
      }
    

    这会处理切换的切换:

    MainPage.xaml.cs

      /// <summary>
      /// Switch the app's theme between light mode and dark mode, and save that setting.
      /// </summary>
      private void ToggleSwitch_Toggled(object sender, RoutedEventArgs e)
      {
         FrameworkElement window = (FrameworkElement)Window.Current.Content;
    
         if (((ToggleSwitch)sender).IsOn)
         {
            AppSettings.Theme = AppSettings.NONDEFLTHEME;
            window.RequestedTheme = AppSettings.NONDEFLTHEME;
         }
         else
         {
            AppSettings.Theme = AppSettings.DEFAULTTHEME;
            window.RequestedTheme = AppSettings.DEFAULTTHEME;
         }
      }
    

    以上所有代码都是为以下ToggleButton 开关创建的:

    MainPage.xaml

    <ToggleSwitch Name="tglAppTheme"
                  Header="Theme"
                  OffContent="Light"
                  OnContent="Dark"
                  IsOn="False"
                  Toggled="ToggleSwitch_Toggled" />
    

    此设置非常简单,有望为某人省去繁重的工作。

    【讨论】:

    • 为什么你的变量会尖叫?
    • @RaulSebastian 只是因为我习惯用大写字母写常量。
    • 在我的情况下,除此之外一切正常; 在开发模式中,我尝试在设置页面中选择深色主题离开。当我重新运行程序时,它首先加载 Light 主题。只有当我进入设置页面时,应用程序才会更改为深色主题。我的案子怎么了?
    • @HninHnin 听起来像是设置未正确保存到本地设置,或者启动应用程序时未在主页上调用主题更改。在 AppSettings 中调试 Theme 属性。
    • 谢谢。现在好了。我将这些行添加到 MainPage 的构造函数中:FrameworkElement root = (FrameworkElement)Window.Current.Content; root.RequestedTheme = AppSettings.Theme;。它有效。
    猜你喜欢
    • 2016-02-18
    • 2010-09-15
    • 1970-01-01
    • 2018-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多