スポンサーサイト

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

画面の起動はビューの仕事らしい(参)

起動するだけならできたけど、当然それだけではどうにもならない。起動前と終了後で、呼び出し側のViewModelで何らかの処理をできるようにする。
/// <summary>実行前処理コマンド</summary>
public static readonly DependencyProperty PreviewStartCommandProperty =
DependencyProperty.Register("PreviewStartCommand",
typeof(ICommand),
typeof(StartWindowAction),
new FrameworkPropertyMetadata(null));

/// <summary>
/// 実行前処理コマンドを取得|設定します。
/// </summary>
public ICommand PreviewStartCommand {
get { return (ICommand)GetValue(PreviewStartCommandProperty); }
set { SetValue(PreviewStartCommandProperty, value); }
}

/// <summary>起動画面終了時処理コマンド</summary>
public static readonly DependencyProperty CallbackClosedCommandProperty =
DependencyProperty.Register("CallbackClosedCommand",
typeof(ICommand), typeof(StartWindowAction),
new FrameworkPropertyMetadata(null));

/// <summary>
/// 起動画面終了時処理コマンドを取得|設定します。
/// </summary>
public ICommand CallbackClosedCommand {
get { return (ICommand)GetValue(CallbackClosedCommandProperty); }
set { SetValue(CallbackClosedCommandProperty, value); }
}
PreviewStartCommandプロパティは、実行前、CallbackClosedCommandプロパティは実行後に処理されるコマンドオブジェクトを指定する。これらがそう機能するように、Executeメソッドのロジックを変更する。
var dataContext = startWindow.DataContext;

if (dataContext != null) {
//BaseWindowVM継承クラスをViewModelとして使っている時
//IsMoalプロパティを渡しておこう。
if (dataContext is BaseWindowVM) {
(dataContext as BaseWindowVM).IsModal = this.IsModal;
}

if (this.PreviewStartCommand != null &&
this.PreviewStartCommand.CanExecute(startWindow.DataContext)) {
this.PreviewStartCommand.Execute(startWindow.DataContext);
}
}
ただ、この処理は、Window生成と同時にViewModelも生成され、DataContextにセットされている事が前提となる。そうならないロジックで実装するときは、DataContextChangedイベントへハンドラを登録し、DataContext設定時に実行する。
//dataContext未設定って事あるのかも?
startWindow.DataContextChanged +=
new DependencyPropertyChangedEventHandler(
StartWindow_DataContextChanged);

/// <summary>
/// 起動ウィンドウ DataContext変更イベント用メソッド
/// </summary>
/// <param name="sender">イベントソース</param>
/// <param name="e">イベントデータ</param>
private void StartWindow_DataContextChanged(
object sender, DependencyPropertyChangedEventArgs e) {

if (e.OldValue != null) {
if (e.OldValue is IDisposable) {
(e.OldValue as IDisposable).Dispose();
}
}

if (e.NewValue != null) {

if (sender is Window &&
e.NewValue is BaseWindowVM) {
//Modal設定
(e.NewValue as BaseWindowVM).IsModal =
WindowBehavior.GetIsModal(sender as Window).GetValueOrDefault();
}

if (this.PreviewStartCommand != null &&
this.PreviewStartCommand.CanExecute(e.NewValue)) {
this.PreviewStartCommand.Execute(e.NewValue);
}
}

return;
}
次に事後にCallbackClosedCommandコマンドが呼び出される様に実装する。モーダルかモードレスかで実装が変わる。
if (this.IsModal) {
startWindow.Owner = this.ownerWindow_;
var dialogResult = startWindow.ShowDialog();

if (dataContext != null &&
dataContext is BaseWindowVM) {
(dataContext as BaseWindowVM).DialogResult = dialogResult;
}

if (this.CallbackClosedCommand != null) {
//コマンドパラメータにはViewModelが設定されます。
this.CallbackClosedCommand.Execute(dataContext);
}

startWindow.DataContext = null;

} else {
startWindow.Closed += new EventHandler(StartWindow_Closed);
startWindow.Show();
}

/// <summary>
/// 起動ウィンドウ終了イベント用メソッド
/// </summary>
/// <param name="sender">イベントソース</param>
/// <param name="e">イベントデータ</param>
private void StartWindow_Closed(object sender, EventArgs e) {

var closedWindow = sender as Window;
closedWindow.Closed -= new EventHandler(StartWindow_Closed);
var dataContext = closedWindow.DataContext;

if (this.CallbackClosedCommand != null) {
//コマンドパラメータにはViewModelが設定されます。
this.CallbackClosedCommand.Execute(dataContext);
}

closedWindow.DataContext = null;
closedWindow.DataContextChanged -=
new DependencyPropertyChangedEventHandler(
StartWindow_DataContextChanged);
return;
}
・モードレス起動時は、Ownerプロパティに親ウィンドウを設定しない。
 設定してしまうと、親ウィンドウを最小化させただけで閉じてしまうから。
・モーダル起動のみDialogResultプロパティを使うことができる。
 モードレスで使おうとすると、たしか例外が発生したような。
・モードレスは、別スレッド的な動きになるので、Closedイベント内でCallbackClosedCommandを実行する。
・コマンド引数には、ViewModelを渡す。
使い方
<tw:StartWindowAction x:Name="ShowWindow2"
WindowType="{x:Type local:Window2}"
IsModal="False"
PreviewStartCommand="{Binding PreviewShowWindow2Command}"
CallbackClosedCommand="{Binding ClosedWindow2Command}"
/>

これで、事前に値を渡したり、事後に結果を取得できるようになる。ただ、これも単一起動用。要件によっては複数起動もありうるので、その時はもう少し改造が必要になる。
スポンサーサイト
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0


この記事へのコメント

コメントの投稿

非公開コメント


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

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

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

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

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