1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[WPF]ReactiveProperty を使用して ViewModelにViewのインスタンスを渡す。

Last updated at Posted at 2021-03-26

※この記事に書かれている方法は、MVVMの原則を壊す恐れがあるため、推奨される方法ではありません。それをご理解の上無理矢理実装したい方向けの記事になります。

最近WPFを書き始めたのですが、MVVMでコードを書いてる時にViewModelでViewのインスタンスが欲しいなーって思うことが時々あったので、取得する方法を忘却録として書いておきます。
個人的にはReactiveProperty無しでC#+WPFでMVVMなコードを書く気にはならないです。
環境: .NET FrameWork4.8,Visual Studio Community 2019
(.NET Coreでも.NET5でもVisual Studio2017 Expressなんかでも動くと思います)

準備

まず前提条件として、View.XamlのDataContextでViewModelを参照します。
PrismなどのMVVMフレームワークを使用しているなら自動的に登録されていたりしますが、そうでないならWindowやUserControlの下にこういった感じで指定します。

MainWindow.xaml
  <Window.DataContext>
     <local:MainWindowViewModel/>
  </Window.DataContext>

①プロジェクト→Nugetパッケージの管理より、ReactiveProperty.WPFを追加します。
画像1.png
②View.xamlに以下の参照を追加します。

MainWindow.xaml
xmlns:bh="http://schemas.microsoft.com/xaml/behaviors"
xmlns:rp="clr-namespace:Reactive.Bindings.Interactivity;assembly=ReactiveProperty.WPF"

③ViewModel.csに以下の参照を追加します。

MainWindowViewModel.cs
using System.Windows;
using Reactive.Bindings;

取得方法

View.xamlにてEventToReactiveCommandを使い、Loadedイベントをコマンドに変換してViewModelに渡します。

MainWindow.xaml
<!--参照の定義の下、ボタンなどの要素の上に書きます。-->
  <bh:Interaction.Triggers>
      <bh:EventTrigger EventName="Loaded">
          <rp:EventToReactiveCommand Command="{Binding LoadCommand}" />
      </bh:EventTrigger>
  </bh:Interaction.Triggers>

受け取ったコマンド内のRoutedEventArgs.SourceからWindowのインスタンスを取得します。
他で使えるように、適当な変数にでも入れておきましょう。

MainWindowViewModel.cs
    public class MainWindowViewModel{

        public ReactiveCommand<RoutedEventArgs> LoadCommand { get; }
        private MainWindow _mainWindow; 

        public MainWindowViewModel() {

            //必要に応じて.addToやClassTerminateなどでオブジェクトの解放を定義しておきます。 
            LoadCommand =
                new ReactiveCommand<RoutedEventArgs>()
                    .WithSubscribe(e => _mainWindow = (MainWindow)e.Source);

           //例えばこんな感じのコマンドを作ってウィンドウを閉じることが出来ます。
           //このコードはメンバ定義もバインディングもしてないのでこのままでは動きません。
           hogehogeCommand=
               new ReactiveCommand()
                   .WithSubscribe(() => _mainWindow.Close());

        }
    }

所感

WindowやWindow内に読み込んだUserControl自体の状態をどこで管理したら良いかよくわからない。
(呼び出したWindowのViewModelに責務があるのか、DIに登録したModelと繋いだほうがいいのか・・・とか)

1
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?