質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.91%

ViewModelのコマンドでクローズをキャンセルする際のOK/キャンセルの取得

受付中

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 3,566

score 15

以下の質問をさせてください。
MVVMのWPFアプリケーションにて、ダイアログを表示し、OKボタンが押された時点でチェックを行い、エラー時はメッセージを表示して
ダイアログを終了しないように考えています。

このダイアログの次の作業の為、OKとキャンセルの判別を行いたく、MVVMのコマンドと別にXAMLにClickイベントの処理を追加しましたが、
DialogResultを設定するとViewModelで何もしなくてクローズされてしまいます。
ViewModelのコマンドでクローズする/しないの処理を入れて、OKとキャンセルの判別を行うにはどうすれば良いでしょうか?

初歩的な質問で申し訳ありませんが、よろしくお願いします。

xxxView.xaml

            <Button Name="OkButton" Content="OK" Command="{Binding OKCommand}" Height="23" Margin="10,0,10,5" Width="80" Click="OkButton_Click"/>
            <Button Name="CancelButton" Content="キャンセル" Command="{Binding CancelCommand}" Height="23" Margin="0,0,0,5" IsCancel="True" Width="80" Click="CancelButton_Click"/>

xxxView.xaml.cs

        private void OkButton_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
        }

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
        }

xxxViewMode.cs

        public void OKCommandDo()
        {
            // エラー発生 メッセージ表示後、ウインドウを閉じない
            return;

            // 保存等の正常処理

            // 終了処理 ウインドウを閉じる
            Messenger.Raise(new WindowActionMessage(WindowAction.Close, "Close"));
        }
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

+2

MVVM(Commandにバインドする)ならClickイベントハンドラは不要です。
代わりにビヘイビアなどを使ってウィンドウを閉じます。
「MVVM Window close Behavior」で検索すればビヘイビアのサンプルはいくらでも出てきます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/14 16:19

    ご回答、ありがとうございます。
    ViewでOK、キャンセルを取得したいわけではありません。
    View以外でOK,キャンセルを取得する方法を知りたかったわけです。
    勿論、Bindされているコマンドを使用するといった方法は理解しておりますが、その上でダイアログボックスをコールした側にOK,キャンセルが押されたことを返す一般的な方法を質問させて頂いておりました。
    そういった質問がMVVMから乖離しているので、一から勉強しなさいということでしたら、この質問は平行線ですね。MVPVMを勉強してみます。

    キャンセル

  • 2018/12/04 15:41

    MVVM=「開発効率を犠牲にしてでも、アプリの具体的な外見・挙動とアプリのコア部分のロジックを分離することによって、保守性や変更容易性を向上させるためのアーキテクチャ」

    MVVMにおける一般的な実装方法、というのはほぼ存在しません。
    juntaroさんが実際問題としてこのトピックで質問しているのは、「この設計でやったらダメっぽいんですが、どういう設計にしたら良いでしょうか?」という質問と本質的に同じです。
    (なので、答えも千差万別です。一般的な設計原則で片付く例でもないので)

    何故かというと、MVVMは「アプリのコアロジックと外見の実装を疎結合にするために、データバインディング機構を有効活用した設計をしましょう。こういう概念的な層(M/V/VM)を作るといいね!」という話でしかないので、具体的な方針についてのガイドラインがないからです。

    で、具体的な例になるとMVVMの一般的な話がもはや関係なくなり、「MVVMアーキテクチャを採用した上で、どういう設計を行うか?」という話にしかならないため、現場の泥臭い保守性と開発効率バランス、要件、実装のコスト、を考慮した上でのケースバイケースにしかならないのです。

    >MVVMではない場面からダイアログを表示する際(ダイアログを表示する箇所がModelを持たない)でも同様ですか?
    Model層に置く必要が存在しないほど単純なロジックであればView層内だけで完結しても問題ないです。
    が、もし検証ロジックが複雑だったり、アプリ状態に依存して動作が変わるなどの要件がある場合には、データ検証や更新、バリデーション、アプリ状態の更新を行う必要があるため、データソースであるModelに処理を依頼して返答を待つ必要があります。

    本題の例であれば、[OK][キャンセル]を押した時点でModel層に存在するクラスにまでViewModelを経由して呼び出しを行い、その結果をイベントなり返り値なりでViewModelに認識させ、ViewModelが認識した結果をそのViewに対して有効な手段でNotificationを行ってViewを更新する(=ダイアログの表示更新、入力抑止、ダイアログWindowのClose等)事になります。
    Livetはその手段を自分で実装しなくていいように便利クラスを提供しているだけなので、用途に合わない道具であれば使わない判断も必要です。

    キャンセル

  • 2018/12/10 20:07

    joy1192さん、長くご丁寧な回答ありがとうございました。
    お返事遅くなり申し訳ありません。

    joy1192さんの言われる通り、私はこの質問の手法が分からない訳ではありません。MVVMを理解していない訳でもありません。
    ただ一般的な方法はどういう手法かというのを理解したく、質問させて頂きました。
    組織で作業を行う際に標準的なコーディングを評定する為の情報を得る為です。

    この件に関して、私も色々と考えてみましたが、joy1192さんの言われていることが、まさしくベストアンサーだと思います。
    ボタンクリックでModelまで情報を持って行き、バリデーション等を行った結果、有効な手段で伝達する。
    手法はケースバイで設計したいと思います。
    以前はLivetを使っておりましたが、現在はPrismを使用しております。
    今後、MVVMライブラリが何を使うかも不明(Xamarin UWP等の他のフレームワークを使用する為)ということもあり、標準というものに拘っていましたが、どのライブラリを使用しても臨機応変に設計をしていこうと思います。(Prismだとこの辺りの伝達が本当に楽ですが)

    joy1192さん、本当にありがとうございました。ベストアンサーを上げられず、申し訳ありません。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.91%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る