redwarrior’s diary

C#, ASP.NET, WEB, G*などの雑多な情報

WPFアプリのMainWindowの終了のキャンセルを、MVVMフレームワークを使用して実装する

WPFアプリケーションで、×ボタンを押してメイン画面を閉じるときに、ある条件を満たす場合は閉じないようにしたい場合があります。言い換えると、終了のキャンセルをしたい場合があります。

コードビハインドを使えば、簡単に実装する事が出来ますが(参考: C#のWPFでWindowを閉じる前に確認する - Ararami Studio)、
MVVMフレームワークを使用している場合は、ViewModelクラスで処理を行いたいです。

色々と調べてやってみたところ、MVVMフレームワークPrismを使用して実装する事が出来たので、やり方を残しておきます。

ボタンも配置していないプロジェクト作成直後の画面を使用します。

f:id:redwarrior:20200805165803p:plain

XAML

<Window x:Class="WindowCloseCancel.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="{Binding Title}" Height="350" Width="525" >
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Closing">
            <prism:InvokeCommandAction Command="{Binding ClosingCommand}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <Grid>
        <ContentControl prism:RegionManager.RegionName="ContentRegion" />
    </Grid>
</Window>

i:EventTriggerタグとprism:InvokeCommandActionタグを使用する事で、ClosingイベントをClosingCommandプロパティに紐づけています。

ViewModel

public class MainWindowViewModel : BindableBase
{
    private string _title = "Prism Application";

    public string Title
    {
        get { return _title; }
        set { SetProperty(ref _title, value); }
    }

    public DelegateCommand<CancelEventArgs> ClosingCommand { get; set; }

    public MainWindowViewModel()
    {
        ClosingCommand = new DelegateCommand<CancelEventArgs>(ExecuteClosing);
    }

    private void ExecuteClosing(CancelEventArgs e)
    {
        e.Cancel = true;
    }
}

ジェネリックなDelegateCommandクラスの型パラメータで指定したものが、コンストラクタの引数のActionクラスの型パラメータにも指定され、Actionクラスに代入するメソッドでは、引数として型パラメータで指定したオブジェクトを受け取る事が出来ます。

言葉にするとややこしいですが、コードビハインドと同様にメソッドを記述できるという事です。今回は、CancelEventArgsだけを使用しましたが、型パラメータを2つ指定すれば、object sender を受け取る事も出来ます。

コードビハインドと同様に、CancelEventArgsクラスのCancelプロパティをtrueにすることで、終了をキャンセルする事が出来ます。

i:EventTriggerタグとprism:InvokeCommandActionタグ、DelegateCommandクラスの組み合わせは、他のイベントでも使用できるため、使い勝手があがりそうです。

.NET Framework、.NET Coreの両方の環境で動作することを確認しました。

開発環境:

  • .NET Core 3.1

  • Prism 7.2.0.1422

以上