スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: スポンサー広告

MVVMで、メッセージボックスを表示する(壱)。

MVVMパターンで、なにげにめんどくさいのがメッセージボックスを表示するという処理。
メッセージボックスはユーザに表示するもので、画面にあらわれてくるので、ビューなんだろうけど、実際に表示したい文字列を設定するのは、VM側となる。でも、MessageBox.ShowをVMには書きたくないし、Showメソッドの第1引数はウィンドウオブジェクトだし。
Livetなんかは、Messengerという機構を使って実現させている。じゃあ、Livetがないとどうにもならないか?といえばそうでもない。表題の通りではあるけど、添付プロパティとCommandを駆使すれば、できなくもない。
ここで記述するのは、仕事で使ったものそのものではなく、「こうもできたな」的な実装とする。
その1:Commandクラス実装。
メッセージボックス表示専用のコマンドを実装する。まずは基底クラス

using System;
using System.Windows.Input;
using System.Windows;

namespace TawamureDays {

/// <summary>
/// メッセージ表示用コマンドクラス
/// </summary>
public abstract class MessageCommand : ICommand {

#region プロパティ

/// <summary>ウィンドウ</summary>
private Window window_;

/// <summary>
/// ウィンドウを取得します。
/// </summary>
protected Window Window {
get {return window_;}
}

#endregion

#region コンストラクタ

/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="window"></param>
public MessageCommand(Window window) {
window_ = window;
}

#endregion

#region ICommandメンバ

/// <summary>変更可否判定値変更イベント</summary>
public event System.EventHandler CanExecuteChanged {
add {CommandManager.RequerySuggested += value;}
remove {CommandManager.RequerySuggested -= value;}
}

/// <summary>
/// メッセージボックスを表示します。
/// </summary>
/// <param name="parameter">パラメータ(メッセージ情報)</param>
public abstract void Execute(object parameter);

/// <summary>
/// メッセージボックス表示が可能かどうかを取得します。
/// </summary>
/// <param name="parameter">パラメータ</param>
/// <returns>true:表示可能</returns>
public bool CanExecute(object parameter) {
return window_ != null && window_.Visibility == Visibility.Visible &&
parameter != null && !string.IsNullOrWhiteSpace(parameter.ToString());
}

#endregion

#region publicメソッド

/// <summary>
/// 内部データをクリアします。
/// </summary>
public void Clear() {
window_ = null;
}

#endregion
}
}
次に、各メッセージ用のクラスを実装する。
情報メッセージ用コマンドクラス

/// <summary>
/// 情報メッセージ用コマンドクラス
/// </summary>
public sealed class InfoMessageCommand : MessageCommand {

#region コンストラクタ

/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="window">ウィンドウ</param>
public InfoMessageCommand(Window window) : base(window) {
}

#endregion

#region MessageCommandメンバ

/// <summary>
/// メッセージを表示します。
/// </summary>
/// <param name="parameter">パラメータ</param>
public override void Execute(object parameter) {

Action<string> action = message => {
MessageBox.Show(this.Window, message,
this.Window.Title,
MessageBoxButton.OK,
MessageBoxImage.Information);
};

if (this.Window.Dispatcher.Thread != System.Threading.Thread.CurrentThread) {
this.Window.Dispatcher.Invoke(action, parameter.ToString());
} else {
action(parameter.ToString());
}
return;
}

#endregion
}

警告用コマンドクラス

/// <summary>
/// 警告メッセージ用コマンドクラス
/// </summary>
public sealed class WarningMessageCommand : MessageCommand {

#region コンストラクタ

/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="window">ウィンドウ</param>
public WarningMessageCommand(Window window) : base(window) {
}

#endregion

#region MessageCommandメンバ

/// <summary>
/// メッセージを表示します。
/// </summary>
/// <param name="parameter">パラメータ</param>
public override void Execute(object parameter) {
Action<string> action = message => {
MessageBox.Show(this.Window, message,
this.Window.Title,
MessageBoxButton.OK,
MessageBoxImage.Warning);
};

if (this.Window.Dispatcher.Thread != System.Threading.Thread.CurrentThread) {
this.Window.Dispatcher.Invoke(action, parameter.ToString());
} else {
action(parameter.ToString());
}

return;
}

#endregion
}

エラー用コマンドクラス

/// <summary>
/// エラーメッセージ用コマンドクラス
/// </summary>
public sealed class ErrorMessageCommand : MessageCommand {

#region コンストラクタ

/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="window">ウィンドウ</param>
public ErrorMessageCommand(Window window) : base(window) {
}

#endregion

#region MessageCommandメンバ

/// <summary>
/// メッセージを表示します。
/// </summary>
/// <param name="parameter">パラメータ</param>
public override void Execute(object parameter) {

Action<string> action = message => {
MessageBox.Show(this.Window, message,
this.Window.Title,
MessageBoxButton.OK,
MessageBoxImage.Error);
};

if (this.Window.Dispatcher.Thread != System.Threading.Thread.CurrentThread) {
this.Window.Dispatcher.Invoke(action, parameter.ToString());
} else {
action(parameter.ToString());
}

return;
}

#endregion
}

最後。確認メッセージ用コマンドクラス

/// <summary>
/// 確認メッセージ用コマンドクラス
/// </summary>
public sealed class ConfirmMessageCommand : MessageCommand {

#region コンストラクタ

/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="window">ウィンドウ</param>
public ConfirmMessageCommand(Window window) : base(window) {
}

#endregion

#region MessageCommandメンバ

/// <summary>
/// 確認メッセージを表示します。
/// </summary>
/// <param name="parameter">パラメータ(stringとAction<bool>のタプル)</param>
public override void Execute(object parameter) {
var param = parameter as Tuple<string, Action<bool>>;

if (param != null) {

Action<string> action = message => {
var result = MessageBox.Show(this.Window, message,
this.Window.Title,
MessageBoxButton.YesNo,
MessageBoxImage.Question);
param.Item2(result == MessageBoxResult.Yes);
};

if (this.Window.Dispatcher.Thread != System.Threading.Thread.CurrentThread) {
this.Window.Dispatcher.Invoke(action, param.Item1);
} else {
action(param.Item1);
}

} else {
var result = MessageBox.Show(this.Window,
"パラメータエラー!",
"ConfirmMsgCommand",
MessageBoxButton.OK,
MessageBoxImage.Error);
}
return;
}

#endregion
}

確認用コマンドクラスだけ、コマンドパラメータを変えている。戻り値が必要なので。別スレッド上で呼び出されても実行できるように、例によってDispatcherを使っている。
次は添付プロパティを実装する。
続く。
スポンサーサイト
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0


この記事へのコメント

コメントの投稿

非公開コメント


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

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

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

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

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。