WinUI3でポモドーロタイマーを作ってみよう！#2

# はじめに

#1で(下記)、環境作成とタイトルの見た目を変更した続きから行う。(全3記事を予定)

https://qiita.com/shisojuice/items/cfe9bdeac44df851c82b

# プロジェクトの作成(#1の続きから)

前回タイトルバーの見た目をWinUIで変更した。

次に、アプリケーションのアイコンを変更する

適当なPng画像を用意(絵が下手なのはさておき🧑‍🎨)

![WinUIWinUI3はじめてみよう2_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777149/3f49152e-dd4c-ef2a-c96d-80d558d2c01e.png)

Package.appxmanifestをダブルクリックで開く、

すべてのビジュアル資産のタブを開き、先ほど用意したPng画像のパスをソースで指定し、生成ボタン押下する。

(既にAssets内に既存でSampleのPng画像が入っているので上書きする)

![WinUIWinUI3はじめてみよう2_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777149/9ff2f950-bffa-8543-5afd-5bc003b3e1ca.jpeg)

この状態でDebugする(PackageでDebug)

タイトルバーが下記のようになる

![WinUIWinUI3はじめてみよう2_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777149/21b7c272-4038-2343-c087-2880d9867937.jpeg)

また、OSのタスクバーのAppのアイコンがSampleから設定した画像になる。

Icon

![WinUIWinUI3はじめてみよう2_4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777149/ea825fc8-5ad1-3201-8b2e-c227bb2b5db9.jpeg)

これでタイトルの変更とアプリケーションアイコンの実装完了！

# サイドのメニューバーを実装する

今回は、タイマー、Todoリスト、設定、の3画面を想定しているので

プロジェクトを右クリックで「新規の項目」を追加して

WinUIで「ページ(Page)」を選択し、追加する。(画面名は、TimerPage、TaskPage、SettingsPageで追加する)

![WinUIWinUI3はじめてみよう2_5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777149/f275dbab-7b78-ff98-f2e6-d6afbd5269e8.jpeg)

![WinUIWinUI3はじめてみよう2_6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777149/5916bf43-5f4f-a977-9af6-3db5174bfb48.jpeg)

MainのWindowが親で、先ほど追加したPageを呼び出すイメージになります。

次に、MainのWindowのデザインで

WinUI 3 Galleryより、サイドのメニューバーは NavigationView　と　メニューアイコンに FontIcon を利用する

```xaml:MainWindow.xaml
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="32"/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <Grid x:Name="AppTitleBar">
            <Image Source="Assets/app.png"
                   HorizontalAlignment="Left" 
                   Width="16" Height="16" 
                   Margin="8,0"/>
            <TextBlock x:Name="AppTitleTextBlock" Text="PomodoroApp"
                       TextWrapping="NoWrap"
                       Style="{StaticResource CaptionTextBlockStyle}" 
                       VerticalAlignment="Center"
                       Margin="28,0,0,0"/>
        </Grid>

        <NavigationView Grid.Row="1" x:Name="navView" PaneDisplayMode="LeftCompact" IsBackButtonVisible="Collapsed" ItemInvoked="navView_ItemInvoked">
            <NavigationView.MenuItems>
                <NavigationViewItem Content="Timer" Tag="timer">
                    <NavigationViewItem.Icon>
                        <FontIcon Glyph="&#xE916;" />
                    </NavigationViewItem.Icon>
                </NavigationViewItem>
                <NavigationViewItem Content="Todo" Tag="task">
                    <NavigationViewItem.Icon>
                        <FontIcon Glyph="&#xE9D5;" />
                    </NavigationViewItem.Icon>
                </NavigationViewItem>
            </NavigationView.MenuItems>
            <NavigationView.FooterMenuItems>
                <NavigationViewItem Content="Settings" Tag="settings">
                    <NavigationViewItem.Icon>
                        <FontIcon Glyph="&#xE713;" />
                    </NavigationViewItem.Icon>
                </NavigationViewItem>
            </NavigationView.FooterMenuItems>
            <Frame x:Name="contentFrame"/>
        </NavigationView>
    </Grid>
```

CS側で先ほどのPageの画面を呼び出す処理を記述する。

```csharp:MainWindow.xaml.cs
        public MainWindow()
        {
            this.InitializeComponent();
            ExtendsContentIntoTitleBar = true;
            SetTitleBar(AppTitleBar);
            
            navView.SelectedItem = navView.MenuItems[0]; 
            navView.IsSettingsVisible = false;
            NavigateToPage("timer");
        }

        private void navView_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
        {
            string tag = args.InvokedItemContainer.Tag.ToString()!;
            NavigateToPage(tag);
        }

        private void NavigateToPage(string tag)
        {
            Type pageType = null;
            switch (tag)
            {
                case "timer":
                    pageType = typeof(TimerPage);
                    break;
                case "task":
                    pageType = typeof(TaskPage);
                    break;
                case "settings":
                    pageType = typeof(SettingsPage);
                    break;
            }

            if (pageType != null && contentFrame.CurrentSourcePageType != pageType)
            {
                contentFrame.Navigate(pageType);
            }
        }

```

下記のようになる

![WinUIWinUI3はじめてみよう2_7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777149/a5d45f86-c08e-1c86-979a-49ce9c616251.jpeg)

これでサイドのメニューバーの実装完了！

# 設定画面を実装する

サウンドのOnOff機能、GihubへのLink、コピーライトを画面に追加する

サウンドのOnOff機能はトグルを使用する

```xaml:SettingsPage.xaml
    <Grid>
        <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
            <ToggleSwitch x:Name="SoundToggleSwitch" HorizontalAlignment="Center" OnContent="Audio On" OffContent="Audio Off" Toggled="Sound_Toggled" />

            <HyperlinkButton HorizontalAlignment="Center" Margin="0,60,0,0" Content="shisojuice on Github" NavigateUri="https://github.com/shisojuice" />
            <HyperlinkButton HorizontalAlignment="Center" Content="This app source on Github" NavigateUri="https://github.com/shisojuice" />
            
            <TextBlock Margin="0,10,0,0" TextAlignment="Center"><Bold>PomodoroApp</Bold></TextBlock>
            <TextBlock TextAlignment="Center"> © 2024 shisojuice.All rights reserved.</TextBlock>
        </StackPanel>
    </Grid>

```

このサウンド設定はアプリケーション全体で適用したいのでApp.xaml.csに下記コードを追記

```csharp:App.xaml.cs
        public static ApplicationDataContainer LocalSettings { get; } = ApplicationData.Current.LocalSettings;
       
        public const string SoundSettingKey = "SoundSetting";


        /// <summary>
        /// Initializes the singleton application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            this.InitializeComponent();
        }

        /// <summary>
        /// Invoked when the application is launched.
        /// </summary>
        /// <param name="args">Details about the launch request and process.</param>
        protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
        {
            m_window = new MainWindow();
            m_window.Activate();
            
            if (LocalSettings.Values.ContainsKey(SoundSettingKey))
            {
                ElementSoundPlayer.State = (bool)LocalSettings.Values[SoundSettingKey] ? ElementSoundPlayerState.On : ElementSoundPlayerState.Off;
            }
        }

```

この設定画面を開いたときに、現在のサウンド設定と一致するようにトグルの初期状態を設定する。

また、トグルを変更した際に、

トグルのOnOffの結果に合わせてアプリケーションのサウンド設定を変化させるイベントを実装する

```csharp:SettingsPage.xaml.cs
        public SettingsPage()
        {
            this.InitializeComponent();
            SoundToggleSwitch.IsOn = ElementSoundPlayer.State == ElementSoundPlayerState.On ? true : false;
        }

        private void Sound_Toggled(object sender, RoutedEventArgs e)
        {
            var toggleSwitch = sender as ToggleSwitch;
            if (toggleSwitch != null)
            {
                ElementSoundPlayer.State = toggleSwitch.IsOn ? ElementSoundPlayerState.On : ElementSoundPlayerState.Off;
                App.LocalSettings.Values[App.SoundSettingKey] = toggleSwitch.IsOn;
            }
        }

```
![WinUIWinUI3はじめてみよう2_8.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777149/26d55296-1163-0953-6d24-fb246443a414.jpeg)

# まとめ

今回は、アプリケーションアイコンの設定、設定画面実装まで行った。

次回で完成予定！ラストスパート頑張ります！

次回につづく。

https://qiita.com/shisojuice/items/7d46c77e67773f3e3de2