C#プログラミング

【C#】MVVMで複数ウィンドを使う方法【サブウィンド】

MVVMで複数ウィンドを使う方法紹介記事のアイキャッチ画像 C#

本記事ではC#(WPF)アプリで複数ウィンドを使用する方法を紹介します。むやみにウィンドを増やすべきではないですが、機能に応じてウィンドを分けることで使いやすいアプリにすることも可能なので、アプリ設計の選択肢を広げるために使いこなせるようになることをお勧めします。

スポンサーリンク

MVVMで複数ウィンドを使用する方法

メインウィンド側のViewModelから、サブウィンド側のViewを生成、表示します。

メインウィンド側のパラメータをサブウィンドに渡したい場合、メインウィンド側ViewModel(自分自身)を引数としてサブウィンドを生成し、サブウィンドにて引数を自身の変数に代入する。

これでサブウィンド側にパラメータを渡せます。

スポンサーリンク

複数ウィンドアプリのサンプルコード

以下のようなアプリを作成しました。MVVM形式で作成しています。

ボタンを押すとサブウィンドが表示されます。その際にテキストデータを渡すのでサブウィンド起動時にそのテキストが表示された状態になります。

作成したアプリのGUIの様子
ボタンを押すとサブウィンドが表示される

必要なファイルをソリューションエクスプローラから追加します。
追加するのはサブウィンド用のViewとviewModelです。

追加するファイル
黄色矢印のファイルを追加

私はファイル名を、SubWindow.xaml、SubViewModel.csとしました。

MainWindow

XAMLは以下の通り。
サブウィンドに渡すテキストボックスとサブウィンドを開くボタンがあります。

<Grid>
    <StackPanel Orientation="Vertical" Margin="20">
        <!-- サブウィンドへ渡すテキスト -->
        <TextBlock Text="サブウィンドに渡すテキスト" />
        <TextBox Text="{Binding txt_toSub}" />
        <!-- サブウィンドを開くボタン -->
        <Button Content="Open SubWindow" Command="{Binding OpenSubWindowBtn_Pushed}"  Margin="20"/>
    </StackPanel>
</Grid>

コードビハインドは以下の通り(いつもの)。

namespace MultiWindow.Views
{
    public partial class MainWindow : Window
    {
        MainViewModel vm = new MainViewModel();
        
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = vm;
        }
    }
}

ViewModelは以下の通り。

namespace MultiWindow.ViewModels
{
    public class MainViewModel : INotifyPropertyChanged
    {
        //コマンド
        public ICommand Button1_Pushed { get; set; }
        public ICommand OpenSubWindowBtn_Pushed { get; set; }


        public MainViewModel()
        {
            //コマンド
            OpenSubWindowBtn_Pushed = new RelayCommand(OpenSubWindow_Cmd);
        }

        //コマンドの処理(サブウィンドに渡すテキスト)
        private void OpenSubWindow_Cmd()
        {
            SubWindow sub_win = new SubWindow(this);
            sub_win.Show();
        }


        //変数(サブウィンドに渡すテキスト)
        private string _txt_toSub;
        public string txt_toSub
        {
            get { return _txt_toSub; }
            set {
                _txt_toSub = value;
                NotifyPropertyChanged("txt_toSub");
            }
        }

        //変数の更新通知用
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
    }
}

SubWindow

XAMLは以下の通り。

<Grid>
    <StackPanel Orientation="Vertical"  Margin="20">
        <TextBlock Text="メインウィンドからのテキスト" />
        <TextBox Text="{Binding sub_text}" />
    </StackPanel>
</Grid>

コードビハインドは以下の通り。
メインウィンドからMainViewModel(m_vm)を受け取ってサブウィンド内で使えるようにする。

namespace MultiWindow.Views
{
    public partial class SubWindow : Window
    {
        public SubWindow(MainViewModel m_vm)
        {
            InitializeComponent();

            //メインウィンドのViewModelを受け取ってサブウィンドを生成
            var s_vm = new SubViewModel(m_vm);

            this.DataContext = s_vm;
        }
    }
}

ViewModelは以下の通り。

namespace MultiWindow.ViewModels
{
    class SubViewModel : INotifyPropertyChanged
    {

        public SubViewModel(MainViewModel m_vm)
        {
            //SubViewModel内の変数に代入する
            sub_text = m_vm.txt_toSub;
        }

        //変数
        private string _sub_text;
        public string sub_text
        {
            get { return _sub_text; }
            set
            {
                _sub_text = value;
                NotifyPropertyChanged("sub_text");
            }
        }

        //変数の更新通知用
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
    }
}
スポンサーリンク

さいごに

今回はサブウィンドの作成方法を紹介しました。
残件としては、サブウィンドが複数開けてしまうこと、メインウィンドを閉じてもサブウィンドが残ることでしょう。
時間があればそこら辺も作ってみようと思います。

コメント

タイトルとURLをコピーしました