web-dev-qa-db-ja.com

フォームの[キャンセル]ボタンをクリックした後に検証をスキップする方法

C#を使用します。編集ボックスと[キャンセル]ボタンがあるWindowsフォームがあります。編集ボックスには、検証イベントのコードがあります。編集ボックスがフォーカスを失うたびにコードが実行されます。 [キャンセル]ボタンをクリックすると、フォームを閉じます。編集ボックスの検証を実行したくない。どうすればこれを達成できますか?

重要な詳細は次のとおりです。検証が失敗した場合、

            e.Cancel = true;

コントロールを離れることを防ぎます。

しかし、ユーザーが[キャンセル]ボタンをクリックすると、フォームは何であれ閉じられます。これはどのように実装できますか?

41
user228985

編集ボックスがフォーカスを失ったときに検証が行われた場合、キャンセルボタンについては何もその発生を止めません。

ただし、検証の失敗によりキャンセルボタンが機能しない場合は、ボタンのCausesValidationプロパティをfalseに設定します。

- 参照: Button.CausesValidationプロパティ

45
Daniel Schaffer

ボタンのCausesValidationプロパティをfalseに設定する必要があることは明らかです。そうすると、検証イベントはクリック時に発生しません。ただし、ボタンの親コントロールのCausesValidationプロパティがtrueに設定されている場合、これは失敗する可能性があります。ほとんどの場合、開発者はコンテナコントロール(パネルコントロールなど)のCausesValidationプロパティを変更するのを忘れたり忘れたりします。これもFalseに設定します。そして、これでうまくいくはずです。

31
Vimal Raj

特定のコントロールの検証が停止していたため、フォームを閉じるのに問題がありました。キャンセルボタンとキャンセルボタンのすべての親に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();
}
21
Ben

[キャンセル]ボタンのCausesValidationプロパティをfalseに設定します。

18
womp

これらの答えはどれも役に立たなかったが、 this thread の最後の答えは役立った。基本的に、次のことが必要です。

  1. [キャンセル]ボタン(ある場合)の.CausesValidationがfalseに設定されていることを確認します
  2. この仮想メソッドをオーバーライドします。

    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人の男を指しています。

4
Wade Hatler

CausesValidationプロパティをfalseに設定します。

4
Brandon

CausesValidationをfalseに設定することが重要ですが、これだけでは不十分です。ボタンの親のCausesValidationがtrueに設定されている場合、検証イベントは呼び出されます。私のケースの1つでは、フォームのパネルにキャンセルボタンがあったため、フォームだけでなくパネルでもCausesValidation = falseを設定する必要がありました。すべてのフォームを通過するよりも簡単だったため、最終的にはプログラムでこれを行いました...

Control control = cancelButton;

while(control != null)
{
   control.CausesValidation = false;
   control = control.Parent;
}
2
Steve Sheldon

Control.CausesValidationプロパティを適切に使用すると、目的を達成するのに役立ちます。

2
Joe

私の場合、フォームでAutoValidateEnableAllowFocusChangeに設定します

1
Alecs

編集ボックスの検証コードのすぐ上に以下を追加します。

if (btnCancel.focused)
  {
     return;
  }

それはそれを行う必要があります。

1
TonyM

Visual Studioウィザードを使用すると、次のようにできます。

enter image description here

1

Daniel Schafferの答えを補完するものとして、編集ボックスがフォーカスを失ったときに検証が発生した場合、 ボタンのアクティブ化を禁止 を実行してローカル検証をバイパスし、とにかく終了できます。

public class UnselectableButton : Button
{
    public UnselectableButton()
    {
        this.SetStyle(ControlStyles.Selectable, false);
    }
}

または、DevExpressを使用する場合:

this.simpleButtonCancel.AllowFocus = false;

これを行うと、キーボードの操作性が変わることに注意してください。タブは、キャンセルボタンにフォーカスを合わせます。

1

たぶん、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);
    }
0
Adiono

これは古い質問ですが、最近この問題に遭遇し、次のように解決しました。

1つ目は、UserControlを、保存およびキャンセルボタンのある 'Shell'Formに読み込んでいます。 UserControlは、Saveの機能を持つインターフェイス(IEditViewなど)を継承します、CancelValidateおよび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;
    }

お役に立てれば。

0
melegant

検証エラーが発生したときにフォームが閉じない理由を調査中に、今日このスレッドを見つけました。

CausesValidation = false閉じるボタンとフォーム自体(Xは閉じる)。

この複雑なフォームでは何も機能していませんでした。

コメントを読みながら、私は完璧に動作するように見えるものを見つけました

フォームの閉じるイベントではなく、閉じるボタン(Xがクリックされたときに発生します)

これでうまくいきました。

AutoValidate = AutoValidate.Disable;
0
TruAG