C#でWPF学習中「メニュー」

C# コンピュータ
C#
WPFでメニューを作ってみました。
スポンサーリンク

実行環境

Windows10 2004
dotnet –version 5.0.104
Visual Studio Code
PowerShell 5.1

プロジェクトの作成

mkdir プロジェクト名
cd プロジェクト名
dotnet new wpf
dotnet add package Microsoft.Xaml.Behaviors.Wpf
dotnet add package ReactiveProperty.WPF
code .

ソースコード

ファイル名:MainWindow.xaml

<Window x:Class="WpfSample13Menu.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:i="clr-namespace:Microsoft.Xaml.Behaviors;assembly=Microsoft.Xaml.Behaviors"
        xmlns:interactivity="clr-namespace:Reactive.Bindings.Interactivity;assembly=ReactiveProperty.WPF"
        xmlns:local="clr-namespace:WpfSample13Menu"
        mc:Ignorable="d"
        Title="{Binding Title.Value}" Height="450" Width="800">
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    <Grid>
        <DockPanel>
            <Menu DockPanel.Dock="Top">
                <MenuItem Header="ファイル">
                    <MenuItem Header="開く" Command="{Binding FileOpenCommand}" />
                    <MenuItem Header="終了" Command="{Binding AppCloseCommand}" />
                </MenuItem>
            </Menu>
        </DockPanel>
    </Grid>
</Window>

ファイル名:MainWindowViewModel.cs

using System.Diagnostics;
using System;
using System.Windows;
using Reactive.Bindings;
using System.ComponentModel;
using System.Linq;
using System.Reactive.Linq;

namespace WpfSample13Menu
{
    public class MainWindowViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public ReactiveProperty<string> Title { get; private set; } = new ReactiveProperty<string>("メニューサンプル");
        public ReactiveCommand FileOpenCommand { get; }  = new ReactiveCommand();
        public ReactiveCommand AppCloseCommand { get; }  = new ReactiveCommand();

        public MainWindowViewModel()
        {
            FileOpenCommand.Subscribe(x => {
                var dlg = new Microsoft.Win32.OpenFileDialog
                {
                    Filter = "テキスト(.txt)|*.txt|全てのファイル(*.*)|*.*",
                };
                var result = dlg.ShowDialog();
                if (result == true)
                {
                    Title.Value = dlg.FileName;
                }
            });

            AppCloseCommand.Subscribe(x => {
                Application.Current.Shutdown();
            });
        }        
        
    }
}

他のソースファイルに変更なし。

説明

XAMLでメニュー項目を階層で表現できる点はすごく良いです。
ViewModel側もReactiveCommandを使うとこで、かなりシンプルに記述できたと思います。
あと、今回XAML内でDataContextのViewModelを指定してみました。それによりMainWindow.xaml.csはコードの修正はありません。
メニューに割り当てた機能としては、ファイル選択のダイアログボックスの起動とアプリケーションの終了となります。
ファイル選択のダイアログボックスでtxtファイルを選択すると、タイトルバーにパスが表示されます。

コメント