Как установить фокус на элемент управления после проверки в .NET - PullRequest
6 голосов
/ 16 декабря 2010

У меня есть приложение WinForm с несколькими элементами управления вводом в форме. В обработчике события проверки (либо Validating, либо Validated) мне нужно определить, какой элемент управления активировать следующим, на основе проверенного значения.

В документации Microsoft о событии Validating говорится:

Внимание

Не пытайтесь установить фокус из обработчиков событий Enter, GotFocus, Leave, LostFocus, Validating или Validated. Это может привести к тому, что ваше приложение или операционная система перестанут отвечать на запросы. Дополнительные сведения см. В разделе WM_KILLFOCUS в разделе «Справочник по вводу с клавиатуры» и в разделе «Блокировка сообщений» в разделе «О сообщениях и очередях сообщений» в библиотеке MSDN по адресу http: // msdn.microsoft.com/library .

Для класса Form существует свойство ActiveControl, позволяющее установить элемент управления, который должен стать активным, без каких-либо ограничений. Я не нашел другого решения после нескольких часов веб-поиска.

Является ли установка свойства ActiveControl (вместо Focus) из моего обработчика события Validated безопасным способом положительной активации нужного элемента управления? Если нет, есть ли решения?

Поскольку .NET Compact Framework не имеет свойства ActiveControl, кто-нибудь может предложить решение?

Ответы [ 4 ]

10 голосов
/ 16 декабря 2010

Да, изменение фокуса во время события валидации довольно хлопотно.Событие возникает в то время, когда фокус меняется.Следующий элемент управления уже получил фокус в отношении Windows, но состояние логической формы все еще имеет фокус на проверяемом элементе управления.Когда вы устанавливаете для e.Cancel значение true, Winforms должен отменить состояние фокуса Windows.Когда вы этого не сделаете, он должен обновить логическое состояние после события.Существует множество факторов, которые могут пойти не так, когда вы сами измените фокус.

Важно дождаться, пока фокус не будет рассортирован.Лучше всего отложить ваш код, пока все не будет выполнено и форма снова не будет работать.Вы можете сделать это с помощью метода Control.BeginInvoke ().Как то так:

    private delegate void ChangeFocusDelegate(Control ctl);

    private void textBox1_Validating(object sender, CancelEventArgs e) {
        int value;
        if (!int.TryParse(textBox1.Text, out value)) e.Cancel = true;
        else {
            if (value == 1) this.BeginInvoke(new ChangeFocusDelegate(changeFocus), textBox2);
            else this.BeginInvoke(new ChangeFocusDelegate(changeFocus), textBox3);
        }
    }
    private void changeFocus(Control ctl) {
        ctl.Focus();
    }
2 голосов
/ 16 декабря 2010

Вы пытались установить для свойства Cancel CancelEventArgs, передаваемого обработчику событий Validating, значение False?

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

private void TextBox1_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
    //Make sure that the textbox is not left blank
    if (string.IsNullOrEmpty(TextBox1.Text))
    {
        e.Cancel = true;
    }
}
0 голосов
/ 14 июня 2012

Эта ветка старая, но у меня есть пара мыслей:

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

  2. Вместо использования события Validating, почему бы не использовать вместо него Leaving?Похоже, что не имеет таких же причуд.

0 голосов
/ 16 декабря 2010
...