C#を使用します。編集ボックスと[キャンセル]ボタンがあるWindowsフォームがあります。編集ボックスには、検証イベントのコードがあります。編集ボックスがフォーカスを失うたびにコードが実行されます。 [キャンセル]ボタンをクリックすると、フォームを閉じます。編集ボックスの検証を実行したくない。どうすればこれを達成できますか?
重要な詳細は次のとおりです。検証が失敗した場合、
e.Cancel = true;
コントロールを離れることを防ぎます。
しかし、ユーザーが[キャンセル]ボタンをクリックすると、フォームは何であれ閉じられます。これはどのように実装できますか?
編集ボックスがフォーカスを失ったときに検証が行われた場合、キャンセルボタンについては何もその発生を止めません。
ただし、検証の失敗によりキャンセルボタンが機能しない場合は、ボタンのCausesValidation
プロパティをfalse
に設定します。
ボタンのCausesValidation
プロパティをfalseに設定する必要があることは明らかです。そうすると、検証イベントはクリック時に発生しません。ただし、ボタンの親コントロールのCausesValidation
プロパティがtrueに設定されている場合、これは失敗する可能性があります。ほとんどの場合、開発者はコンテナコントロール(パネルコントロールなど)のCausesValidation
プロパティを変更するのを忘れたり忘れたりします。これもFalseに設定します。そして、これでうまくいくはずです。
特定のコントロールの検証が停止していたため、フォームを閉じるのに問題がありました。キャンセルボタンとキャンセルボタンのすべての親にcontrol.CausesValidation = false
を設定しました。しかし、まだ問題がありました。
ユーザーが検証を使用していたフィールドの編集中に、あきらめることにした場合(フィールドに無効な入力を残す)、キャンセルボタンイベントが発生していましたが、ウィンドウは閉じませんでした。
これは、キャンセルボタンのクリックイベントで次のように修正されました。
private void btnCancel_Click(object sender, EventArgs e)
{
// Stop the validation of any controls so the form can close.
AutoValidate = AutoValidate.Disable;
Close();
}
[キャンセル]ボタンのCausesValidation
プロパティをfalse
に設定します。
これらの答えはどれも役に立たなかったが、 this thread の最後の答えは役立った。基本的に、次のことが必要です。
この仮想メソッドをオーバーライドします。
protected override bool ProcessDialogKey(Keys keyData) {
if (keyData == Keys.Escape) {
this.AutoValidate = AutoValidate.Disable;
CancelButton.PerformClick();
this.AutoValidate = AutoValidate.Inherit;
return true;
}
return base.ProcessDialogKey(keyData);
}
私は実際に答えたわけではなく、実際に行った2人の男を指しています。
CausesValidation
プロパティをfalse
に設定します。
CausesValidationをfalseに設定することが重要ですが、これだけでは不十分です。ボタンの親のCausesValidationがtrueに設定されている場合、検証イベントは呼び出されます。私のケースの1つでは、フォームのパネルにキャンセルボタンがあったため、フォームだけでなくパネルでもCausesValidation = falseを設定する必要がありました。すべてのフォームを通過するよりも簡単だったため、最終的にはプログラムでこれを行いました...
Control control = cancelButton;
while(control != null)
{
control.CausesValidation = false;
control = control.Parent;
}
Control.CausesValidation
プロパティを適切に使用すると、目的を達成するのに役立ちます。
私の場合、フォームでAutoValidateをEnableAllowFocusChangeに設定します
編集ボックスの検証コードのすぐ上に以下を追加します。
if (btnCancel.focused)
{
return;
}
それはそれを行う必要があります。
Daniel Schafferの答えを補完するものとして、編集ボックスがフォーカスを失ったときに検証が発生した場合、 ボタンのアクティブ化を禁止 を実行してローカル検証をバイパスし、とにかく終了できます。
public class UnselectableButton : Button
{
public UnselectableButton()
{
this.SetStyle(ControlStyles.Selectable, false);
}
}
または、DevExpressを使用する場合:
this.simpleButtonCancel.AllowFocus = false;
これを行うと、キーボードの操作性が変わることに注意してください。タブは、キャンセルボタンにフォーカスを合わせます。
たぶん、BackgroundWorkerを使用して少し遅延させたいので、検証を実行するかどうかを決定できます。フォームを閉じる際の検証を回避する例を次に示します。
// The flag
private bool _isClosing = false;
// Action that avoids validation
protected override void OnClosing(CancelEventArgs e) {
_isClosing = true;
base.OnClosing(e);
}
// Validated event handler
private void txtControlToValidate_Validated(object sender, EventArgs e) {
_isClosing = false;
var worker = new BackgroundWorker();
worker.DoWork += worker_DoWork;
worker.RunWorkerAsync();
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
}
// Do validation on complete so you'll remain on same thread
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
if (!_isClosing)
DoValidationHere();
}
// Give a delay, I'm not sure this is necessary cause I tried to remove the Thread.Sleep and it was still working fine.
void worker_DoWork(object sender, DoWorkEventArgs e) {
Thread.Sleep(100);
}
これは古い質問ですが、最近この問題に遭遇し、次のように解決しました。
1つ目は、UserControlを、保存およびキャンセルボタンのある 'Shell'Formに読み込んでいます。 UserControlは、Saveの機能を持つインターフェイス(IEditViewなど)を継承します、Cancel、ValidateおよびToggleValidate。
シェルフォームでは、次のようにマウス入力とマウス終了を使用しました。
private void utbCancel_MouseEnter(object sender, EventArgs e)
{
((Interface.IEdit)tlpMain.Controls[1]).ToggleValidate();
}
private void utbCancel_MouseLeave(object sender, EventArgs e)
{
((Interface.IEdit)tlpMain.Controls[1]).ToggleValidate();
}
次に、ToggleValidateで(2つのコントロールを備えたシンプルなフォームを言う...必要に応じていつでもリストをループできます)、CausesValidationを設定します。
public bool ToggleValidate()
{
uneCalcValue.CausesValidation = !uneCalcValue.CausesValidation;
txtDescription.CausesValidation = !txtDescription.CausesValidation;
return txtDescription.CausesValidation;
}
お役に立てれば。
検証エラーが発生したときにフォームが閉じない理由を調査中に、今日このスレッドを見つけました。
CausesValidation = false
閉じるボタンとフォーム自体(Xは閉じる)。
この複雑なフォームでは何も機能していませんでした。
コメントを読みながら、私は完璧に動作するように見えるものを見つけました
フォームの閉じるイベントではなく、閉じるボタン(Xがクリックされたときに発生します)
これでうまくいきました。
AutoValidate = AutoValidate.Disable;