WPFで2画面構成のアプリを製作していました。これをPrismを用いたMVVMパターンに書き換えようとしています。  
単純化した例:

  * いまWPFのウィンドウとして`MainWindow,SubWindow`クラスがあります。
  * `MainWindow`にあるボタンをクリックすると、`Button_Click`が呼ばれて、`SubWindow`が表示されます。
  * `MainWindow.xaml.cs`は次のようになっています:

```

    public partial class MainWindow : Window
    {
        SubWindow sub;
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (sub == null)
            {
                sub = new SubWindow();
                sub.Closed += (s, _e) => sub = null;
                sub.Show();
             }
             sub.Activate();
        }
    }
    
```

これと等価な処理をPrismで書くにはどうすればよいのでしょうか。ViewやViewModelにおいて`SubWindow`のインスタンスを生成したり、これを`Show,Activate`したりするのはMVVM的ではないと思うので、どうやって実現するのかわからなくなってしまいました。

必要なのは、例示したコードにあるとおり

  * ボタンを押すと、`SubWindow`が表示される。すでに表示されているときは、新たにインスタンスをつくるのではなく、アクティブにするだけ
  * `ShowDialog`ではない（`MainWindow`も操作できる）

といった動作です。

関連するかもしれない話として、`IDialogService`のサンプル(<https://prismlibrary.com/docs/wpf/dialog-
service.html>)を確認してみたものの、そのままだと`SubWindow`にあたる画面が複数表示されてしまう上にアクティブにするというメソッドが見当たらず、上記のような動作を実現する方法はわかりませんでした。

以上、よろしくお願いいたします。
CC BY-SA 4.0
2020-07-18T16:29:43.910
68714
2020-07-22T08:16:40.243
41145
question
c# wpf mvvm
Prism(MVVMパターン)でサブウインドウ(ダイアログではない)を開く方法
たとえば、  
デリゲートを用いて、MainWindowを呼び出す「外側」のクラスから機能を入れ込む方法があります。  
画面を閉じる処理も記載しています；

MainWindowViewModel：

```

    public Action RequestClose;
    public Action RequestToSubWindow;
    public Action<string> RequestToSubWindow2;
    
```

App.xaml.cs：

```

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        var wnd = new MainWindow();
        var mainVM = new MainWindowViewModel();
    
        // When the ViewModel asks to be closed, close the window.
        mainVM.RequestClose += delegate {
            wnd.Close();
        };
        mainVM.RequestToSubWindow += displaySubWindow;
        mainVM.RequestToSubWindow2 += displaySubWindow2;
    
        wnd.DataContext = mainVM;
        wnd.Show();
    }
    // SubWindow の ViewModel に引数を持たせない場合
    private static Action displaySubWindow = () => {
        var subWnd = new SubWindow();
        var subVM = new SubViewModel();
    
        // When the ViewModel asks to be closed, close the window.
        subVM.RequestClose += delegate
        {
            subWnd.Close();
        };
        subWnd.DataContext = subVM;
    
        subWnd.ShowDialog();
    };
    // SubWindow の ViewModel に引数を持たせる場合
    private static Action<string> displaySubWindow2 = (name_) => {
        var subWnd2 = new SubWindow2();
        var subVM2 = new Sub2ViewModel(name_);
    
        // When the ViewModel asks to be closed, close the window.
        subVM2.RequestClose += delegate
            {
                subWnd2.Close();
            };
        subWnd2.DataContext = subVM2;
    
        subWnd2.Show();
    };
    
```

参考サイト：  
<https://docs.microsoft.com/ja-jp/archive/msdn-
magazine/2009/february/patterns-wpf-apps-with-the-model-view-viewmodel-design-
pattern>

* * *

質問の「MVVM的ではない」には頷けますが、Microsoftドキュメントに記載されています。  
こちらの回答は露骨なコードで綺麗とは言えないので、他の方法があれば私も使ってみたいと思います。
CC BY-SA 4.0
2020-07-22T07:45:05.310
68820
2020-07-22T08:16:40.243
2020-07-22T08:16:40.243
38266
38266
68714
answer