Chapter 39

ステップ11-2: 続き1

Apterygiformes-zenn
Apterygiformes-zenn
2022.01.20に更新

設定ページ コントロール配置

SettingsPage.xamlWindowxmlns:ui=~を追加し、
Page.ResourcesToggleSwitchのスタイルを追加します。

SettingsPage.xaml
 <Page x:Class="DarkLightMode_1.Pages.SettingsPage"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
       xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
       xmlns:local="clr-namespace:DarkLightMode_1.Pages"
+      xmlns:ui="http://schemas.modernwpf.com/2019"
       mc:Ignorable="d" 
       d:DesignHeight="450" d:DesignWidth="800"
       Title="SettingsPage">
 
+    <Page.Resources>
+        <Style TargetType="ui:ToggleSwitch">
+            <Setter Property="Margin"
+                    Value="0,5" />
+        </Style>
+    </Page.Resources>
 
     <Grid>
         
     </Grid>
 </Page>

Gridレイアウトの種類の変更 > StackPanelで変更し、
TextBlock, RadioButtonを3つ、TextBlockの順に配置します。

Page.Resourcesにラジオボタンのスタイルを追加します。

<!-- テーマラジオボタンスタイル -->
<Style x:Key="ThemeRadioStyle"
        TargetType="RadioButton"
        BasedOn="{StaticResource DefaultRadioButtonStyle}">
    <Setter Property="GroupName"
            Value="Theme" />
</Style>

StackPanelの中身を以下のように編集し、ソリューションのリビルドをします。

<TextBlock Text="テーマ"
            Style="{StaticResource TitleTextBlockStyle}" />
<RadioButton x:Name="ThemeSystem"
                Content="Windows テーマを使用"
                Style="{StaticResource ThemeRadioStyle}" />
<RadioButton x:Name="ThemeLight"
                Content="ライト"
                Style="{StaticResource ThemeRadioStyle}" />
<RadioButton x:Name="ThemeDark"
                Content="ダーク"
                Style="{StaticResource ThemeRadioStyle}" />

<TextBlock Text="その他"
            Style="{StaticResource TitleTextBlockStyle}"
            Margin="0,20,0,0" />

その他の下にトグルスイッチを2つ、XAML手書きします。

<ui:ToggleSwitch x:Name="Option1"
                    Header="何かのオプション1" />
<ui:ToggleSwitch x:Name="Option2"
                    Header="何かのオプション2" />

ラジオボタン処理

ラジオボタンのスタイルに以下を追加します。

<EventSetter Event="Click"
                Handler="ThemeRadio_Click" />

ThemeRadio_Clickの部分にテキストカーソルを置いてF12キーを押して定義へ移動します。
クリック時の処理に以下を書きます。

var ctrl = sender as Control;
if (ctrl == ThemeLight)
{
    ThemeManager.Current.ApplicationTheme = ApplicationTheme.Light;
}
else if (ctrl == ThemeDark)
{
    ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark;
}
else
{
    ThemeManager.Current.ApplicationTheme = null;
}

足りないusingを追加してラジオボタンの処理は完成です。

テーマ切り替え動作確認

実行してみます。
設定ページを開きます。

ラジオボタンの選択を変えて配色が変わることを確認します。

動作確認できたら終了します。

設定ページのイベント処理

PageLoadedLostFocusイベントハンドラを作成します。

Loadedの処理
try
{
    ReadSettings();
}
catch (Exception ex)
{
    MessageBox.Show(ex.ToString());
}
LostFocusの処理
try
{
    WriteSettings();
}
catch (Exception ex)
{
    MessageBox.Show(ex.ToString());
}

とりあえずここまで作ります。

設定読み書き

1)

設定画面の設定値を設定ファイルに保存する仕組みを作ります。
ソリューションエクスプローラーでSettingsフォルダを作成し、その中に以下のクラスを作成します。

  • Settings
  • SettingsReader
  • SettingsWriter

2)

Settingsクラスのアクセス修飾子をinternalからpublicに変更し、以下のように編集します。
設定画面の設定値を保持する入れ物です。

Settings.cs
/// <summary>
/// アプリケーション設定
/// </summary>
public class Settings
{
    /// <summary>
    /// テーマ
    /// </summary>
    public string? Theme { get; set; } = null;

    /// <summary>
    /// 何かの設定1
    /// </summary>
    public bool Option1 { get; set; } = true;

    /// <summary>
    /// 何かの設定2
    /// </summary>
    public bool Option2 { get; set; } = false;
}

3)

SettingsReader.csを以下のように編集します。
設定ファイルを読み込んでSettingsクラスに入れて返す機能です。

SettingsReader.cs
using System.IO;
using System.Text.Json;

namespace DarkLightMode_1.Settings
{
    /// <summary>
    /// アプリケーション設定読み込み
    /// </summary>
    internal class SettingsReader
    {
        /// <summary>
        /// 設定ファイルパス
        /// </summary>
        private readonly string _filePath;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="filePath">設定ファイルパス</param>
        public SettingsReader(string filePath)
        {
            _filePath = filePath;
        }

        /// <summary>
        /// 設定ファイルからアプリケーション設定読み込み
        /// </summary>
        /// <returns></returns>
        public Settings ReadFromFile()
        {
            if (!File.Exists(_filePath))
            {
                // ファイルがなければ初期値を返す
                return new Settings();
            }

            // ファイル読み込み
            string jsonStr = File.ReadAllText(_filePath);
            var stg = JsonSerializer.Deserialize<Settings>(jsonStr);

            return stg ?? new Settings();
        }
    }
}

4)

SettingsWriter.csを以下のように編集します。
Settingsクラスの内容を設定ファイルに保存する機能です。

SettingsWriter.cs
using System.IO;
using System.Text.Json;
using JE = System.Text.Encodings.Web;
using UN = System.Text.Unicode;

namespace DarkLightMode_1.Settings
{
    /// <summary>
    /// アプリケーション設定書き込み
    /// </summary>
    internal class SettingsWriter
    {
        /// <summary>
        /// 設定ファイルパス
        /// </summary>
        private readonly string _filePath;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="filePath">設定ファイルパス</param>
        public SettingsWriter(string filePath)
        {
            _filePath = filePath;
        }

        /// <summary>
        /// 設定ファイル書き込み
        /// </summary>
        /// <param name="stg"></param>
        public void WriteToFile(Settings stg)
        {
            var opt = new JsonSerializerOptions
            {
                // シリアライズするUnicodeの範囲
                Encoder = JE.JavaScriptEncoder.Create(UN.UnicodeRanges.All),
                // インデントする
                WriteIndented = true,
            };

            // JSONオブジェクトを文字列化
            string jsonStr = JsonSerializer.Serialize(stg, opt);
            // ファイル書き込み
            File.WriteAllText(_filePath, jsonStr);
        }
    }
}