【WPF】【ModernWpfUI】NavigationViewを使ってツールバーを作る

はじめに

以前PythonとPyQt6を使ってツールバーを作りました。


今回WPFで同様のことを行います。

今回作成したツールバー
以前PyQt6で作成したツールバー

問題点

  • PyQt6の時と違ってツールバーを展開した時に右の領域が収縮していません。


  • 自前のアイコン画像を使う方法がわかりません。

方法

ModernWpfUIのインストール

NuGetからインストールしました。
インストール後に以下の変更が必要なようです。

App.xamlの変更

以下の2つを追加しました。

xmlns:ui="http://schemas.modernwpf.com/2019"
<ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
        <ui:ThemeResources />
        <ui:XamlControlsResources />
        <!-- Other merged dictionaries here -->
    </ResourceDictionary.MergedDictionaries>
    <!-- Other app resources here -->
</ResourceDictionary>

最終的にはこうなります。

<Application x:Class="WpfApp1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApp1"
             StartupUri="MainWindow.xaml"
             xmlns:ui="http://schemas.modernwpf.com/2019">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ui:ThemeResources />
                <ui:XamlControlsResources />
                <!-- Other merged dictionaries here -->
            </ResourceDictionary.MergedDictionaries>
            <!-- Other app resources here -->
        </ResourceDictionary>
    </Application.Resources>
</Application>

MainWindow.xamlの変更

以下の2行を追加しました。

xmlns:ui="http://schemas.modernwpf.com/2019"
ui:WindowHelper.UseModernWindowStyle="True"

最終的にはこうなります。

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        xmlns:ui="http://schemas.modernwpf.com/2019"
        ui:WindowHelper.UseModernWindowStyle="True">
    <Grid>

    </Grid>
</Window>

ボタンの作成

ここからはXAMLファイルには記述せずコードファイルに記述していきます。

この方法が良いわけではありません。

クラスの作成

public class EachMenu
{
    public string text;
    public ui.Symbol icon;
    public Type page;

    public EachMenu(string _text, ui.Symbol _icon, Type _page)
    {
        text = _text;
        icon = _icon;
        page = _page;
    }
}

ボタンの定義

List<EachMenu> menu_list = new List<EachMenu>()
    {
        new EachMenu("Home", ui.Symbol.Home, typeof(Home)),
        new EachMenu("Settings", ui.Symbol.Setting, typeof(Settings)),
        new EachMenu("Exit", ui.Symbol.Cancel, typeof(Settings))
    };

MainWindow.xaml.cs

最終的にはこのようになりました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using ui = ModernWpf.Controls;

namespace WpfAppNaviView
{
    public partial class MainWindow : Window
    {
        List<EachMenu> menu_list = new List<EachMenu>()
            {
                new EachMenu("Home", ui.Symbol.Home, typeof(Home)),
                new EachMenu("Settings", ui.Symbol.Setting, typeof(Settings)),
                new EachMenu("Exit", ui.Symbol.Cancel, typeof(Settings))
            };

        ui.NavigationViewItem[] naviitems;

        ui.Frame mainFrame = new ui.Frame();

        public MainWindow()
        {
            InitializeComponent();

            ui.NavigationView naviview = new ui.NavigationView();
            naviview.IsBackButtonVisible = ui.NavigationViewBackButtonVisible.Collapsed;
            naviview.IsSettingsVisible = false;
            naviview.OpenPaneLength = 150; 
            naviview.SelectionChanged += NaviView_SelectionChanged;
            naviview.Content = mainFrame;

            naviitems = new ui.NavigationViewItem[menu_list.Count()];
            for (int i = 0; i < menu_list.Count(); i++)
            {
                naviitems[i] = new ui.NavigationViewItem();
                naviitems[i].Content = menu_list[i].text;
                naviitems[i].Icon = new ui.SymbolIcon(menu_list[i].icon);
                naviitems[i].Tag = menu_list[i].page;
                naviview.MenuItems.Add(naviitems[i]);
            }

            Content = naviview;
        }
        private void NaviView_SelectionChanged(ui.NavigationView sender, ui.NavigationViewSelectionChangedEventArgs args)
        {
            var selectedItem = (ui.NavigationViewItem)args.SelectedItem;

            mainFrame.Navigate((Type)selectedItem.Tag);
        }
        public class EachMenu
        {
            public string text;
            public ui.Symbol icon;
            public Type page;

            public EachMenu(string _text, ui.Symbol _icon, Type _page)
            {
                text = _text;
                icon = _icon;
                page = _page;
            }
        }
    }
}

各ページ

ページは「プロジェクト」→「ページの追加(WPF)」で行いました。

Home.xaml.cs

using System.Windows;
using System.Windows.Controls;

namespace WpfAppNaviView
{
    public partial class Home : Page
    {
        TextBlock txt = new TextBlock();
        public Home()
        {
            InitializeComponent();

            txt.HorizontalAlignment = HorizontalAlignment.Center;
            txt.VerticalAlignment = VerticalAlignment.Center;
            txt.FontSize = 60;
            txt.Text = "ホーム画面";

            Content = txt;
        }
    }
}

Settings.xaml.cs

using System.Windows;
using System.Windows.Controls;

namespace WpfAppNaviView
{
    public partial class Settings : Page
    {
        Grid mainGrid = new Grid();
        public Settings()
        {
            InitializeComponent();

            Button Btn1 = new Button() { Content = "button1" };
            Button Btn2 = new Button() { Content = "button2" };

            Btn1.HorizontalAlignment = HorizontalAlignment.Stretch;
            Btn1.VerticalAlignment = VerticalAlignment.Stretch;
            Btn1.Margin = new Thickness(40);

            Btn2.HorizontalAlignment = HorizontalAlignment.Stretch;
            Btn2.VerticalAlignment = VerticalAlignment.Stretch;
            Btn2.Margin = new Thickness(40);

            Grid.SetRow(Btn1, 0);
            Grid.SetRow(Btn2, 1);

            mainGrid.RowDefinitions.Add(new RowDefinition());
            mainGrid.RowDefinitions.Add(new RowDefinition());

            mainGrid.Children.Add(Btn1);
            mainGrid.Children.Add(Btn2);

            Content = mainGrid;
        }
    }
}

参考にさせて頂いたサイト

[WPF] NavigationView(ナビゲーションビュー)を使う - Qiita