Закрытие формы окон С#, избегая проверки текстового поля

Это вопрос С# winform. У меня есть текстовое поле с проверяющим прослушивателем событий для проверки содержимого текстового поля на регулярное выражение.

После проверки, если введенное значение неверно, я показываю окно сообщения, и я отменяю событие, чтобы курсор мыши возвращался в текстовое поле с неправильным значением.

Это нормально работает, когда я выхожу из этого текстового поля в другие кнопки/текстовые поля.

Но когда я ввожу неправильное значение и закрываю форму (с кнопкой закрытия в правом верхнем углу), он проверяет содержимое текстового поля и выдает сообщение, а форма не закрывается, поскольку я выполняю касецию события.

Проблема в том, что когда я нажимаю кнопку X в правом верхнем углу формы, я не хочу, чтобы проверка была уволена, потому что я все равно закрываю форму. Как я могу это сделать?

Я отправлю фрагмент кода как можно скорее.

Ответ 1

Чтобы использовать проверочные обработчики, такие как обработчик 'txtIPAddress_Validating(), приведенный ниже, имея возможность закрыть форму без ввода допустимых записей для этого, я делаю следующее:

1) Инициировать проверки обработчиков. Из свойств управления элемента управления, для которого вы хотите активировать проверку, дважды щелкните событие "Проверка" из этого списка контрольных событий. Доступ к списку контрольных событий можно получить, щелкнув эту панель инструментов панели свойств объекта управления (молния). Затем вы можете ввести код в автоматически созданный обработчик с именем, объединяющим имя элемента управления и "_Validating". Часть этого обработчика, где что-то установлено как недействительное, может принудительно ввести действительные записи, добавив команду "e.Cancel = true".

Для таких примеров метода проверки см. Ниже код txtIPAddress_Validating() 'и' txtMaskBits_Validating(). Не отвлекайтесь на весь механизм проверки этих конкретных примеров. Все, что вам нужно, чтобы увидеть и воспроизвести в своем собственном коде для принудительной проверки, - это добавить инструкцию "e.Cancel = true" в нужном месте вашего собственного метода проверки. То есть когда значение идентифицируется как недопустимое.

На этом этапе проверка должна работать нормально, но любая попытка закрыть форму вызовет проверку, которая остановится и будет настаивать на действительных значениях, прежде чем сможет закрыть форму. Это не всегда то, что вы хотите. Когда это не так, я продолжаю следующее.

2) Кнопка "Отмена", которая также отменяет (отключает) все проверки:

a) Поместите обычную кнопку "Отмена" в форме, связанной с таким методом, как метод "btnCancel_Click()" ниже.

б) перед обычным 'this.close();' введите команду "AutoValidate = AutoValidate.Disable;" инструкция. Эта инструкция отключает все триггеры проверки. Обратите внимание, что событие "btnCancel_Click" запускается до того, как произойдет какая-либо проверка. Это не так для событий закрытия формы, которые будут выполняться после проверки событий. Вот почему эта проверка не может быть отключена из любого из этих событий закрытия формы.

c) Для правильной работы этой кнопки "Отмена" вам также необходимо установить свойство "CausesValidation" этой кнопки "Отмена" на "false". Это необходимо, иначе нажатие на эту кнопку приведет к проверке, прежде чем проверка может быть отключена с помощью вышеперечисленного "AutoValidate = AutoValidate.Disable;" инструкция.

На этом этапе вы должны уйти, нажав кнопку "Отмена", не вводя правильные значения. Однако нажатие на верхнюю правую кнопку "X" окна формы все равно будет принудительно проверять.

3) Сделать верхнюю правую кнопку "X" также отменить проверку:

Задача здесь заключается в том, чтобы захватить такое событие "X" нажатием, прежде чем выполняется проверка. Любая попытка сделать это с помощью обработчика закрытия формы не будет работать, потому что уже слишком поздно, когда выполнение достигает такого обработчика. Однако щелчок кнопки "X" можно быстро захватить, переопределив метод WndProc() и проверив условие "m.Msg == 0x10". Когда это условие истинно, ранее введенный "AutoValidate = AutoValidate.Disable;" инструкция снова может быть использована для отключения общей проверки в этом случае. См. Метод WndProc() ниже для образца кода такого метода. Вы должны иметь возможность копировать и вставлять этот метод, как в класс формы.

На этом этапе кнопки "Отменить" и "X" должны отменять валидации. Однако ключ эвакуации, который можно использовать для закрытия формы, не работает. Такой ключ запуска активируется, когда свойство "CancelButton" используется для связывания этого ключа эвакуации с формой "Отмена".

4) Сделать клавишу эвакуации также отменой проверки:

Подобно кнопке "X", клавиша эвакуации может быть захвачена путем переопределения существующего метода. Это метод ProcessDialogKey(). Еще один раз, ранее введенный "AutoValidate = AutoValidate.Disable;" инструкция может использоваться для отключения общей проверки для ключа эвакуации. См. "Переопределенный метод ProcessDialogKey() в коде ниже, чтобы узнать, как это можно сделать. Здесь вы также сможете копировать и вставлять этот метод, как в свой собственный класс формы.

На этом этапе вы должны быть сделаны!

Дальнейшие соображения:

Хорошо заметить, что следующие два других способа закрыть окно также должны отлично работать на этом этапе. Этими двумя способами являются:

  • Параметр "Закрыть" кнопки значка верхнего левого окна.
  • Нажатие Alt + F4, которое запускает те же действия закрытия, что и вышеописанная опция "Закрыть".

Эти два способа закрытия окна начали отменять проверку, как только вы представили механизм захвата кнопки "X", описанный в пункте 3 выше.

Это для меня до сих пор. Надеюсь, это поможет!

Мой пример кода ниже:

public partial class frmMyIP : Form
{
    public frmMyIP()
    {
          InitializeComponent();
    }

    // To capture the Upper right "X" click
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x10) // The upper right "X" was clicked
        {
            AutoValidate = AutoValidate.Disable; //Deactivate all validations
        }
        base.WndProc(ref m);
    }

    // To capture the "Esc" key
    protected override bool ProcessDialogKey(Keys keyData)
    {
        if (keyData == Keys.Escape)
        {
            AutoValidate = AutoValidate.Disable;
            btnCancel.PerformClick(); 
            return true;
        }
        return base.ProcessDialogKey(keyData);
    }
    public bool IsValidIP(string ipaddr)
    {
        string pattern = @"^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])"+
        @"(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$";

        Regex check = new Regex(pattern);
        bool valid = false;

        if (ipaddr == "")
        {
            valid = false;
        }
        else
        {
            valid = check.IsMatch(ipaddr, 0);
        }

        return valid;
    }

    private void txtIPAddress_Validating(object sender, CancelEventArgs e)
    {
        string address = txtIPAddress.Text;
        if (!IsValidIP(address))
        {
            MessageBox.Show("Invalid IP address!");
            e.Cancel = true;
        }
    }

    private void cmbMaskBits_Validating(object sender, CancelEventArgs e)
    {
        int MaskBitsValue = Convert.ToInt32(cmbMaskBits.Text);

        if (MaskBitsValue<1 || MaskBitsValue>30)
        {
        MessageBox.Show("Please select a 'Mask Bits' value between 1 and 30!");
        e.Cancel = true;
        }
    }

    private void btnCancel_Click(object sender, EventArgs e)
    {
        // Stop the validation of any controls so the form can close.
        // Note: The CausesValidation property of this <Cancel> button
        //       must also be set to false.

        AutoValidate = AutoValidate.Disable;
        this.Close();
    }

Ответ 2

private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
    // Assume that X has been clicked and act accordingly.
}

Создайте событие закрытия, а затем просто отмените свой валидатор.

Ответ 3

В качестве первой строки в событии проверки текстового поля вставьте следующую строку:

//Allow the form to be closed
if (this.ActiveControl.Equals(sender))
    return;

Поскольку событие закрытия формы запускает проверку, и поскольку это (как правило, по крайней мере) будет единственным событием формы, которое инициирует проверку, мы можем сделать предположение о том, что любая проверка события события формы является закрытым событием.

Ответ 5

Вам нужна реализация, подобная описанной ниже, где предполагается, что у вас есть кнопка "Сохранить" и кнопка "Отмена" для формы:

    public Form1()
    {
        // Disable validation in constructor
        textBox.CausesValidation = false;
    }

    private void OnSaveClicked(object sender, EventArgs e)
    {
        textBox.CausesValidation = true;
        if (ValidateChildren())
        {
            //
            // Do saving of the form data or other processing here ....
            //
            Close();
        }
        //
        // Set validation to false, as user may press Cancel next
        //
        textBox.CausesValidation = false;
    }

    private void OnCancelClicked(object sender, EventArgs e)
    {
        Close();
    }

Ответ 6

Проверьте, какая кнопка имеет фокус в проверке проверки. Если кнопка отмены (и в моем случае - кнопка очистки), переопределите. Это внутренний метод, который я вызываю из проверочного обработчика событий моей ячейки. (Просто понял, что это вопрос С#, но вы можете перевести)

Private Sub validateCell(ByVal tagDesc As String, ByVal userInput As String, ByVal legalRegex As String, ByVal regexDesc As String, ByVal e As DataGridViewCellValidatingEventArgs)
    Dim match As Match = Regex.Match(userInput, legalRegex)
    Dim matches = match.Groups()
    Dim val = match.Value
    If val.Length = 0 Or userInput.Length > val.Length Then
        tagGrid.Rows(e.RowIndex).ErrorText = _
            tagDesc & " must match pattern:  " & regexDesc
        If Me.Cancel_Button.Focused Or Me.clearButton.Focused Then
            e.Cancel = False
            tagGrid.Rows(e.RowIndex).ErrorText = ""
        Else
            e.Cancel = True
            MsgBox(tagDesc & " must match pattern:  " & regexDesc, MsgBoxStyle.Critical)
        End If
    Else
        e.Cancel = False
        tagGrid.Rows(e.RowIndex).ErrorText = ""
    End If
End Sub

Ответ 7

Я пришел сюда в поисках простого метода, чтобы закрыть форму, когда обработчик события Validating вызывает исключение, сообщает об этом и требует, чтобы форма закрылась. После прочтения этой темы и многих других, после которой последовал второй день эксперимента, я сделал несколько открытий и разработал простой хак, чтобы заставить форму закрыть.

Во-первых, во-первых; Я обнаружил, что когда событие Validating вызывает this.Close() флаг FormClosingEventArgs.Cancel, переданный в его процедуру события From_Closing, имеет значение TRUE, что фактически приводит к тому, что событие отменяет себя. И наоборот, нормальное событие Close принимает флаг FormClosingEventArgs.Cancel, установленный в FALSE.

Поскольку метод Close в форме не принимает аргументов, нет прямого способа заставить проблему, порождая необходимость взлома. В этой статье обсуждается ряд таких хаков, но я считаю, что мой гораздо проще реализовать.

Взлом начинается с простой булевой переменной уровня.

    bool _fExceptionIsFatal = false;

Помимо определения обработчика события Form_Closing, это единственное структурное изменение, которое требуется для формы.

Событие Form_Closing прост.

    private void From1_Closing ( object sender , FormClosingEventArgs e )
    {
        if (this.CausesValidation )
        {   // There is no sense repeating this procedure if another routine already did it.
            DisableValidation ( );
        }   // if (this.CausesValidation )          

        if ( _fExceptionIsFatal )
        {   // Cancel False == Allow form to close.
            e.Cancel = false;
        }   // if ( _fExceptionIsFatal )
    }   // From1_Closing

Хотя функция DisableValidation реализована как локальный метод текущей формы, то же самое можно было бы сделать, передав ссылку Form в библиотечную процедуру, поскольку форма является формой, а ее коллекция Controls - это коллекция Controls, period. Вскоре я сделаю это, а также выполнив его инверсию, чтобы снова включить проверку.

    private void DisableValidation ( )
    {
        foreach ( Control ctrl in this.Controls )
        {
            ctrl.CausesValidation = false;
        }   // foreach ( Control ctrl in this.Controls )

        this.CausesValidation = false;
    }   // DisableValidation

Четвертая часть решения одинаково проста; всякий раз, когда вы хотите принудительно закрыть форму, установите для _intValueAsInteger значение TRUE, прежде чем вы вызовите this.Close.

Ответ 8

Добавьте код ниже в форму. Вы можете закрыть форму, даже проверка элементов управления детьми.

protected override void WndProc(ref Message m)
{
    if (m.Msg == 0x10) // The upper right "X" was clicked
    {
        this.ActiveControl = null;
        this.AutoValidate = AutoValidate.Disable;
    }
    base.WndProc(ref m);
 }

Ответ 9

Фактический ответ смехотворно прост по сравнению со всеми предложениями здесь, которые включают в себя хаки и лишний лишний код, чтобы отменить что-то.

"Трюк" - это просто, чтобы фокус мог меняться, а не проверять огонь от кнопок на самой форме.

Вы можете просто установить два свойства в форме:

MyForm.CausesValidation = false;
MyForm.AutoValidate = AutoValidate.EnableAllowFocusChange;

Et voila, форма действует нормально, когда вы пытаетесь закрыть ее, и проверка по-прежнему работает с другими входами, такими как tab с изменением фокуса или щелчками мыши.