Changing Theme in Windows 10 UWP App Programmatica

2019-01-25 10:52发布

问题:

I was able to change theme using this.RequestedTheme = ElementTheme.Dark; But what I need is the whole application level, since this one only change the theme of the current page to dark.

Whenever I try this App.Current.RequestedTheme = ApplicationTheme.Dark; I always get this error

An exception of type 'System.NotSupportedException' occurred in UWPApp.exe but was not handled in user code

Is there such a way that I can change the whole application theme from Light to Dark or vice versa?

I'm using VS2015

回答1:

Updated answer with what I finally decided on.

I used a settings class that holds all of the apps settings including what theme to use. Since the theme can only be set when it starts we need to make sure to set it them. This is the code I used:

In the App.xaml.cs file:

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

    this.InitializeComponent();
}

In the App.xaml file make sure to remove this property:

    RequestedTheme="Light"

If its not removed it always default to light with no way to change it.

This way the user can choose the theme, it gets stored and used when the app starts. Just make sure to load it and apply it in the app initialization phase.



回答2:

Application's RequestedTheme can only be updated in constructor.However (as you discovered) , Page's RequestedTheme can be updated anytime in runtime.

This is really annoying I know and there's not much information about this situation other than this MSDN page :

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

The theme can only be set when the app is started, not while it’s running. Attempting to set RequestedTheme while the app is running throws an exception (NotSupportedException for Microsoft .NET code). If you give the user an option to pick a theme that's part of app UI, you must save the setting in the app data and apply it when the app is restarted.

There should be workarounds but they'll be very dumb.Microsoft doing this in their own official apps like Groove though ...

My solution is doing theme updating on the Element level , not the Application level.

  1. Create your own BasePage (inherited from Page)
  2. Keep your settings under a static class and create an Event for keep tracking the model changes.
  3. In your BasePage's constructor listen to this event and apply changes when there's.

I'm not able to provide code example right now (since i'm very busy today) , but this is by far the most efficient way IMHO.



回答3:

I found another solution that worked pretty well for me. If the app has a root frame that loads the pages (which is the case by default), I could set the requested theme of that root frame to the desired value and the theme of the app got changed without restarting. The code looks like this:

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

I got that snippet from the Windows Template Studio GitHub repository here, so this seems to be kind of the best way to do this.