2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【WPF】viewを作成する際のテンプレートコード【C#】

Posted at

概要

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のBindableBaseDelegateCommandは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);
        }        
    }
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?