C#でWPF学習中「別ウィンドウを表示する」その2

コンピュータ

ソースコード

ファイル名:MainWindow.xaml

<Window x:Class="DialogSample1.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:DialogSample1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    <Grid>
        <StackPanel>
            <Button Content="押す" Command="{Binding PushButtonCommand}" />
        </StackPanel>
    </Grid>
</Window>

ファイル名:MainWindowViewModel.cs

using System.ComponentModel;
using Reactive.Bindings;

using System.Diagnostics;

namespace DialogSample1;

public class MainWindowViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;
    protected virtual void OnPropertyChanged(string name)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    public ReactiveCommand PushButtonCommand { get; } = new();
    public ReactiveProperty<string> Field { get; set; } = new("aaa");
    public MainWindowViewModel()
    {
        PushButtonCommand.Subscribe(e =>
        {
            var sub = new SubWindow()
            {
                DataContext = this,
            };

            bool result = sub.ShowDialog() ?? false;

            Debug.Print($"result:{result} Value:{Field.Value}");
        });
    }

}

ファイル名:SubWindow.xaml

<Window x:Class="DialogSample1.SubWindow"
        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:DialogSample1"
        mc:Ignorable="d"
        Title="SubWindow" Height="450" Width="800">
    <Grid>
        <StackPanel>
            <TextBox Text="{Binding Field.Value}" />
            <StackPanel Orientation="Horizontal">
                <Button Name="okButton" Click="okButton_Click" IsDefault="True">OK</Button>
                <Button Name="cancelButton" IsCancel="True">Cancel</Button>
            </StackPanel>
        </StackPanel>
    </Grid>
</Window>

ファイル名:SubWindow.xaml.cs

using System.Windows;

namespace DialogSample1;
public partial class SubWindow : Window
{
    public SubWindow()
    {
        InitializeComponent();
    }
    private void okButton_Click(object sender, RoutedEventArgs e) =>
        DialogResult = true;

    private void cancelButton_Click(object sender, RoutedEventArgs e) =>
        DialogResult = false;
}

説明

前回と異なる点はSubWindow用のViewModelがなくMainWindowのViewModelをSubWindowsにも適用しています。

MainWindowとSubWindowはいずれもWindowクラスから派生したクラスであり、基本的に同じものだと考えらます。
ただ、MainWindowの生成部分は隠蔽(システム側が作成?)されていますが、SubWindowの生成はコードを書く必要があります。
SubWindow生成後DataContextプロパティにViewModelをセットします。

            var sub = new SubWindow()
            {
                DataContext = this,
            };

サンプルプログラムではDataContextにthis(自分自身=ViewModel)をセットしています。
その後sub.ShowDialog()でSubWindowを表示します。
ViewModelのプロパティの値がバインドしているのでテキストボックスの初期値として表示されています。

SubWindowのテキストボックスの値を変更した後、SubWindowを閉じてMainWindowに戻るとバインドしているViewModelのプロパティの値も変更されていることが確認できました。

コメント