web-dev-qa-db-ja.com

プログラムによるWindows 10 UWPアプリのテーマの変更

this.RequestedTheme = ElementTheme.Dark;を使用してテーマを変更することができましたが、現在のページのテーマをダークに変更するだけなので、必要なのはアプリケーションレベル全体です。

私がこれを試したときはいつでもApp.Current.RequestedTheme = ApplicationTheme.Dark;いつもこのエラーが出ます

タイプ 'System.NotSupportedException'の例外がUWPApp.exeで発生しましたが、ユーザーコードでは処理されませんでした

アプリケーションのテーマ全体を明から暗に、またはその逆に変更できる方法はありますか?

VS2015を使用しています

14
AlMusal

最終的に私が最終的に決定したことで答えを更新しました。

使用するテーマを含むすべてのアプリ設定を保持する設定クラスを使用しました。テーマは開始時にのみ設定できるため、必ず設定する必要があります。これは私が使用したコードです:

App.xaml.csファイルで:

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

    this.InitializeComponent();
}

App.xamlファイルで、必ずremoveこのプロパティを確認してください。

    RequestedTheme="Light"

削除されていない場合は、常にデフォルトで点灯し、変更することはできません。

このように、ユーザーはテーマを選択できます。テーマは保存され、アプリの起動時に使用されます。必ずロードして、アプリの初期化フェーズで適用してください。

16
Threezool

アプリケーションの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の一部であるテーマを選択するオプションをユーザーに提供する場合は、設定をアプリのデータに保存し、アプリの再起動時に設定を適用する必要があります。

回避策はあるはずですが、非常に馬鹿げています。Microsoftは、Grooveのような独自の公式アプリでこれを行っています...

私の解決策は、アプリケーションレベルではなく、要素レベルでテーマを更新することです。

  1. 独自のBasePageを作成します(Pageから継承)
  2. 設定を静的クラスの下に保持し、モデルの変更を追跡し続けるためのイベントを作成します。
  3. BasePageのコンストラクターでこのイベントをリッスンし、存在する場合は変更を適用します。

現在コード例を提供することはできません(今日は非常に忙しいためです)が、これはIMHOを圧倒的に効率的に実行する方法です。

10

私にはかなりうまくいく別の解決策を見つけました。アプリにページをロードするルートフレームがある場合(デフォルト)、そのルートフレームのリクエストされたテーマを目的の値に設定すると、アプリのテーマが変更されます再起動せずに。コードは次のようになります。

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

私はそのスニペットをWindows Template Studio GitHubリポジトリ here から取得したので、これはこれを行うための最良の方法のようです。

6
alxnull

アプリの実行中にテーマを設定できるため、 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" />

このセットアップは非常に簡単で、うまくいけば誰かの面倒な作業を省くことができます。

3