MVVM Show View パターン1 Viewのコードビハインド

## Viewを表示するパターンを考える
MVVMを勉強しはじめた時に、いったいコードをどうかけばいいのかさっぱり分からなかったのことは、Viewを表示するコードをどこに書くのか？
今でもそれらが曖昧なので、明確にしておくためにこの記事を書きます。
ただし、調べると、より分からない点がさらに増えました。
フィードバックを頂けるとありがたいです。

## Newする順序
V・VM・MをNewする順序も、パターンによって異なります。それにも留意します。

## 結合・参照？
MVVMでは、ModelはViewModelを知らないし、ViewModelはViewを知らない、ことが前提です。
この知らない、というのは、**名前を知っているだけなのは知るうちに入るのか入らないのか。この点がよくわかりません。**
例えば、SubView.xamlを新しく表示する場合、SubViewという確定している名前がコードに書かれているだけなら、それで知っていることになるのか？ということです。
これについては、パターン2の、Commandパラメータで考えます。


## コード
https://github.com/mikihiro-t/MVVMPattern

## 開発環境
.NET Core 3.1 + ReactiveProperty で構築します。

# パターン 1　Viewのコードビハインド
アプリを起動した時の最初のViewは、App.xamlのStartupUriで指定します。
それ以降のViewを、Viewのコードビハインドから表示します。

## ファイルの構成
| | Class |
|:-:|:-:|
|**Model**|MainManager|
|**ViewModel**|MainViewModel|
|**View**|MainView|


Newする順序は、

1. ViewからViewModelをNew
2. NewされたViewModelから、ModelをNewします。

V →　VM　→　M　の順序です。

## プロジェクトの構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/fca4934e-d900-a7f5-1f27-94b312bdfc0e.png)

## スタート時のウインドウ
App.xamlの、StartupUriに、MainView.xamlを指定しました。


```C#
<Application
    x:Class="ShowView1.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ShowView1"
    StartupUri="View/MainView.xaml">
```

## MainViewのコードビハインド
MainViewModelをNewしています。
DataContextに、vmをセットします。ここではなく、XAMLでVMを指定もできます。
ただし、ViewのコードビハインドでVMのメソッドを呼び出すことがあるなら、ここで指定しておくと便利だと思います。

```C#
  public partial class MainView : Window
    {
        MainViewModel vm = new MainViewModel();
        public MainView()
        {
            InitializeComponent();
            this.DataContext = vm;
        }
```

## ViewModel
ModelをNewして保持します

```C#
    class MainViewModel : INotifyPropertyChanged, IDisposable
    {
        public MainManager Model { get; }

        public MainViewModel()
        {
            Model = new MainManager();
```


## ボタンクリックで新しいViewを表示
ボタンをクリックして、別のViewを表示するには、

```C#
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var cls = new MainView();
            cls.Show();
        }
```

Viewのコードビハインドで良いはずです。
ここでは、2つめのMainViewを表示しています。

## Viewと他のViewとの関係
ここでは、ボタンクリックで、MainViewをさらに表示していますが、他のViewを表示するのも同じです。

SubViewがあるとすれば、

* MainViewのボタンクリック
* SubViewを表示

になります。
これだと、MainViewは、SubViewを知っていることになります。SubViewという名前を知っているし、参照もしています。MVVMとして、それで良いのかどうかが分かりません。

View1が、View2を、表示する処理（閉じる処理も？）を、View1で行って良いとすると、また、例えば、View2のDialogResultを、View1で受け取り、ViewModel, ViewModel経由でModelで処理をする程度のこともOKかもしれません。

## Viewのコードビハインドの是非
Viewには、できるだけコードを書かないでおこうという考え方もあるのですが、私は次の条件の時は、Viewにコードを書くと良いと考えます。

* Viewに関わる事
* Viewのコードで処理した方が、ViewModelやModelで処理するより容易

XAMLに書くのも、Viewにコードビハインドで書くのも同じViewでの処理です。単に、言語がXAMLなのかC#なのか程度の違いです。
https://stackoverflow.com/a/37294259/9924249

XAMLだけで処理をしようとして、複雑なコードになるのは本末転倒な気がします。また、UIのテストが行いやすくなるからXAMLだけで処理をしようとするのも、同様に本末転倒に思います。

## 同様の例
Handle it in the view
https://stackoverflow.com/a/5829704/9924249

```C#
private void AddCustomerView_Click(object sender, RoutedEventArgs e)
{
    AddCustomerView view = new AddCustomerView(data);
    view.Show();
}
```

となっています。ここでは、ViewをNewする時に、引数としてdataを渡していますが、このdataはモデルのデータであるはずです。それを、Viewから渡すことは、MVVMらしいでしょうか？　これも分からない点です。

## 疑問点まとめ

* Viewが他のViewを知っているのはMVVMとしてそれでよいのか？
* ViewからViewを表示する場合、引数（Modelのデータ）をどうやって渡すのか？

単純な処理なようで、疑問も増えました。このパターンを基本として、他のパターンと比べていきましょう。

## 記事予定
* パターン1　Viewのコードビハインド（この記事）
* パターン2　[Commandパラメータ](https://qiita.com/hiro_t/items/b177c40e03d22ef24068)
* パターン3　[Prism の Dialog Service](https://qiita.com/hiro_t/items/61a50d9f6308195c3536)
* パターン4　引数を渡す（予定）