【C#】フォーム終了時のValidating、Validatedイベントを制御する
Visual C# 2012
.NET Framework 4.5
入力エリアコントロールにあるCausesValidationプロパティはデフォルトではtrue。
そのため、何も意識しなければ、Validating、Validatedイベントは走行し、フォーカスを失った時に入力値を検証し、OKならフォーカス移動させる、NGならフォーカス移動させないということが可能だ。
その動作を利用して、フォームを閉じた時に制御を加えよう。
フォームを閉じる時にValidatingの結果に応じて制御を変更したい
FormClosingイベントは、直前にカーソルが存在したコントロールで走行したValidatingイベントのe.Cancel値を引き継いで走行される。
よって、
Validatingイベントの結果に応じて、フォームを閉じる/閉じないを制御する、というのは、以下のようなコードで実装可能。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void textBox1_Validating(object sender, CancelEventArgs e) { // 何かの入力条件の関係で入力値を拒否する if ("hoge".Equals(textBox1.Text)) { MessageBox.Show("入力値が不正です。"); e.Cancel = true; } } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { // Validatingでエラーだった時、後続処理もせず、フォームを閉じない if (e.Cancel) { return; } switch (MessageBox.Show("変更されています。保存しますか?", this.Text, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)) { case DialogResult.Cancel: e.Cancel = true; return; case DialogResult.No: e.Cancel = false; return; default: // 保存処理とかの結果 bool result = false; if (!result) { MessageBox.Show("保存に失敗しました。"); e.Cancel = true; return; } return; } } } }
フォームを閉じる時にValidatingを走行させたくない
FormにあるAutoValidateプロパティをDisableにするとValidatingイベントは走行しなくなる。
しかし、FormClosingイベント内で記述しても、それより先にValidatingイベントが走行するため、希望する動作はしない。
そこで、WndProcメソッドをオーバーライドし、フォームが閉じられたというメッセージを取得して制御することで実現可能。
恐らく、これがもっとも簡単な制御方法だ。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void textBox1_Validating(object sender, CancelEventArgs e) { // 何かの入力条件の関係で入力値を拒否する if ("hoge".Equals(textBox1.Text)) { MessageBox.Show("入力値が不正です。"); e.Cancel = true; } } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { // Validatingの走行有無をデフォルトに戻す this.AutoValidate = AutoValidate.Inherit; // Validatingでエラーだった時、後続処理もせず、フォームを閉じない if (e.Cancel) { return; } switch (MessageBox.Show("変更されています。保存しますか?", this.Text, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)) { case DialogResult.Cancel: e.Cancel = true; return; case DialogResult.No: e.Cancel = false; return; default: // 保存処理とか bool result = false; if (!result) { MessageBox.Show("保存に失敗しました。"); e.Cancel = true; return; } return; } } protected override void WndProc(ref Message m) { // 画面終了のメッセージが届いた時、Validatingが走行しないようにする const int WM_SYSCOMMAND = 0x112; const int SC_CLOSE = 0xF060; if (m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_CLOSE) { this.AutoValidate = AutoValidate.Disable; } base.WndProc(ref m); } } }