概要
xamlで新しくwindow (view) を作成する際の、テンプレートとなるサンプルコードを記載してみました。
仕様
- Windowに「OK」と「キャンセル」ボタンが配置されており、どちらを押下してもWindowが閉じる挙動です。
- 使用する側 (viewやviewModelをnewし、
ShowDialog()
する側) で「OK」と「キャンセル」どちらのボタンが押されたかを判定することができます。 - Window右上の「×」ボタンが押された場合も、「キャンセル」ボタンと同じように扱われます。
コード
View
View.xaml
<Window
x:Class="Hoge.Views.View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="サンプルビュー"
Width="800"
Height="400"
ResizeMode="NoResize">
<Grid>
<!-- OK、キャンセルボタン -->
<StackPanel
Orientation="Horizontal">
<Button
Width="90"
Height="20"
Click="OKButton_Click"
Command="{Binding OKCommand}"
Content="OK"/>
<Button
Width="90"
Height="20"
Click="CancelButton_Click"
Command="{Binding CancelCommand}"
Content="Cancel"/>
</StackPanel>
</Grid>
</Window>
View.xaml.cs
/// <summary>
/// View.xaml の相互作用ロジック
/// </summary>
public partial class View : Window
{
/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="vm">ViewModel</param>
public View(ViewModel vm)
{
InitializeComponent();
this.DataContext = vm;
}
/// <summary>
/// OKボタンクリック
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OKButton_Click(object sender, RoutedEventArgs e) => this.Close();
/// <summary>
/// キャンセルボタンクリック
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CancelButton_Click(object sender, RoutedEventArgs e) => this.Close();
}
ViewModel
public class ViewModel : BindableBase
{
/// <summary>
/// キャンセルしたか
/// </summary>
public bool IsCancel { get; private set; } = true;
/// <summary>
/// OKボタン
/// </summary>
public ICommand OKCommand => _okCommand ?? (_okCommand = new DelegateCommand(() =>
{
try
{
IsCancel = false;
}
catch (Exception ex)
{
//エラー処理
}
}));
private ICommand _okCommand;
/// <summary>
/// キャンセルボタン
/// </summary>
public ICommand CancelCommand => _cancelCommand ?? (_cancelCommand = new DelegateCommand(() =>
{
try
{
IsCancel = true;
}
catch (Exception ex)
{
//エラー処理
}
}));
private ICommand _cancelCommand;
}
ViewModelのBindableBase
やDelegateCommand
はprismを使用しています。
使用方法
var vm = new ViewModel();
// 画面起動
new View(vm).ShowDialog();
if (vm.IsCancel)
{
// 「キャンセル」や右上の「×」ボタンが押下された場合の処理
}
終わりに
ViewModelのIsCancel
の初期値がtrue
になっているため、「×」ボタンでも「キャンセル」ボタンと同様の扱いになります。
※なので、厳密にはキャンセルボタンを押下した際のIsCancel = true;
を入れる処理は不要です。
また、「OK」ボタン押下しても、例えば内部チェック等に引っかかり、再度この画面を表示する場合にViewModelを使いまわすと、もちろんIsCancelの
値がfalse
になっているため、「×」ボタン押下時の挙動が変わってしまいます。なのでその場合は、再度ViewModelをnewするか、仕様的にそれが難しいならViewModelにIsCancel
の値を初期値のtrue
に戻すメソッドを用意し、再度表示する場合はそのメソッドを通す形で対応できます。この形だと、例えばViewで押下されている沢山のボタンをViewModelで保持している場合だと、前回の押下状態を保持したまま再度Viewを表示できます。
以下はViewを再表示する場合に、ViewModelを使いまわしているサンプルコードです。
ViewModel.cs
/// <summary>
/// キャンセルしたか
/// </summary>
public bool IsCancel { get; private set; } = true;
/// <summary>
/// キャンセルフラグをデフォルト値に設定する
/// </summary>
public void InitIsCancelFlag() => IsCancel = true;
使用方法
private void SampleMethod()
{
ViewModel vm = null;
while (true)
{
if (vm == null)
{
// 初回起動する場合
vm = new ViewModel();
}
else
{
// 再度起動する場合
vm.InitIsCancelFlag();
}
// 画面起動
new View(vm).ShowDialog();
if (vm.IsCancel)
{
// 「キャンセル」や右上の「×」ボタンが押下された場合の処理
return;
}
// 画面の入力項目のエラーチェック
var result = IsValid(vm, out string message);
if (result) break;
// エラーメッセージ表示
MessageBox.Show(message, "チェック結果", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}