ViewModel側から画面終了を通知(要求)してみた。

画面(View)側から終了する事は、簡単にできる。×ボタンを押すだけだし。
その終了をVM側に通知するのは、OnClosingなんかをバインディングさせれば、可能となる。
では、VM側から終了を通知したい時はどうしよう?
組み込み(ビルトインコマンド)を使おうか?
ApplicationCommands.Close プロパティ
使い方
[C#][WPF]コマンドですよ その8 「用意されてるコマンド」
ん?でもこれ、Closeを呼び出すのにメソッド登録してるなぁ…。
MVVMにしようと思ったら、どうするんだろ?
どうやってDialogResultプロパティに結果を設定するんだろ?と。
・結果(true or false)を決めるのは、ViewModel側
・画面を実際に閉じるのは、View側
結果として、仕事では、カーソス変更同様、コマンドで実装することにした。
なお、DialogResultは、モーダル起動でのみ設定可能。モーダレス(モードレス)で設定すると、例外が発生する。
○View側コード(抜粋)
using System;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Controls;
using System.Windows.Data;

namespace TawamureDays.Controls {

using TawamureDays.Commands;//RelayCommandクラスを格納中
using TawamureDays.Extensions;//各種Behaviorクラスを格納中

/// <summary>
/// マスターページならぬ、マスターコンテンツ用コントロール。<br/>
/// (下記コードは抜粋したもの)<br/>
/// </summary>
[System.Windows.Markup.ContentProperty("Content")]
public class TawamureContents : ContentControl {

#region コンストラクタ

/// <summary>
/// コンストラクタ
/// </summary>
public TawamureContents() {

//DataContext側のRequestCloseCommandプロパティと
//「OneWayToSource」でバインディング
BindingOperations.SetBinding(
this,
TawamureContents.RequestCloseCommandProperty,
new Binding("RequestCloseCommand"){
Mode = BindingMode.OneWayToSource});

requestCloseCommand_ = new RelayCommand(ExecuteRequestCloseCommand);
return;
}

#endregion

#region 依存関係プロパティ

/// <summary>
/// 画面終了要求コマンドを取得|設定します。
/// </summary>
public ICommand RequestCloseCommand {
get {return (ICommand)GetValue(RequestCloseCommandProperty);}
set {SetValue(RequestCloseCommandProperty, value);}
}

/// <summary>画面終了要求コマンド</summary>
public static readonly DependencyProperty RequestCloseCommandProperty =
DependencyProperty.Register("RequestCloseCommand", typeof(ICommand),
typeof(TawamureContents), new UIPropertyMetadata(null));

#endregion

#region ContentControlメンバ

/// <summary>
/// 依存関係プロパティ値 変更イベントハンドラ
/// </summary>
/// <param name="e">イベント引数</param>
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) {
base.OnPropertyChanged(e);

if (e.Property.Name == "DataContext") {
if (e.NewValue != null) {
//終了要求用コマンドを設定します。
//このタイミングで設定することで、VM側に設定されます。
this.RequestCloseCommand = requestCloseCommand_;
}
}

return;
}

#endregion

#region 内部変数

/// <summary>画面終了要求コマンド</summary>
private RelayCommand requestCloseCommand_;

#endregion

#region RequestCloseCommandメソッド

/// <summary>
/// RequestCloseCommand実行用メソッド<br/>
/// VM側からの終了要求に対して処理を行います。<br/>
/// </summary>
/// <param name="parameter">コマンドパラメータ(bool型)</param>
private void ExecuteRequestCloseCommand(object parameter) {

var window = Window.GetWindow(this);

if (window == null) {
window = Application.Current.Windows.OfType<Window>().
Where(w => w.IsActive).SingleOrDefault();
if (window == null) {
return;
}
}

try {
if (parameter == null) {
window.DialogResult = false;
window.Close();

} else {
bool result;

if (WindowBehavior.GetIsModal(window).GetValueOrDefault()) {
//モーダル起動
if (bool.TryParse(parameter.ToString(), out result)) {
window.DialogResult = result;
} else {
window.DialogResult = false;
}
}
}

} catch (Exception) {
MessageBox.Show(window, "終了時にエラーが発生しましたよ", "エラー",
MessageBoxButton.OK,
MessageBoxImage.Hand);
} finally {
window.Close();
window = null;
}

return;
}

#endregion
}
}

○ViewModel側コード(抜粋)
using System;
using System.Windows.Input;

namespace TawamureDays.ViewModels {

using TawamureDays.Commands;

/// <summary>
/// ウィンドウ用ViewModelの基底クラス
/// </summary>
public class BaseWindowVM : BaseViewModel {

#region プロパティ

/// <summary>
/// 画面終了要求を取得|設定します。
/// </summary>
public ICommand RequestCloseCommand {
get; set;
}

#endregion

#region protectedプロパティ/メソッド

/// <summary>
/// 結果を取得します。
/// </summary>
public bool? Result {
get; protected set;
}

/// <summary>
/// 画面終了を実行します。
/// </summary>
/// <param name="result">true:OKで終了, false:Cancelで終了</param>
protected void RequestClose(bool result) {
Result = result;
this.RequestCloseCommand.Execute(result);
}

#endregion
}
}

で、使い方

/// <summary>
/// 終了ボタンコマンド 実行メソッド
/// </summary>
/// <param name="parameter">パラメータ</param>
private void ExecuteCloseCommand(object parameter) {
this.RequestClose(true);
return;
}
スポンサーサイト
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0


この記事へのコメント

コメントの投稿

非公開コメント


サイドバー背後固定表示サンプル

当ブログに書かれたソースコードは流用自由です。

バグ、スペルミス等はありうる事です。

ご利用の際は自己責任でお願いしますm(_ _)m