Как я могу установить errorProvider против ВСЕХ недопустимых элементов управления формы при использовании this.validateChildren()?

Извините, если я упускаю из виду что-то очевидное здесь.

Контекст проблемы

У меня есть приложение, которое позволяет пользователю заполнить форму, содержимое которой будет загружено в базу данных. Когда они нажимают кнопку «Загрузить», форма должна быть подтверждена. Пользователь будет предупрежден, если какие-либо поля недействительны.

Текущее решение

Когда пользователь нажимает кнопку для загрузки транзакции, вызывается validFormSelections().

if (!this.validateChildren())
{
    // Display an error
    return false;
}
else
{
    return true; 
}

Для каждого поля со списком вызывается метод проверки, например.

cmbName_Validating(object sender, CancelEventArgs e)
{
    if (/* not valid for whatever reason */)
    {
        errorProvider.Clear();
        e.Cancel = true; 
        errorProvider.setError((Control)sender, /* suitable error message */)
    }
    else
    {
        errorProvider.SetError((Control)sender, ""); 
    }
} 

Проблема

Что я хотел бы сделать, так это показать errorProvider рядом с всеми полями, которые недействительны, однако на данный момент, поскольку e.Cancel = true; в отдельном методе проверки, то (если я правильно понимаю) это не так продолжить проверку других полей, как только будет найдено первое недопустимое поле.

Как я могу сделать так, чтобы я мог вызывать this.validateChildren() и по-прежнему отображать errorProvider рядом со всеми недопустимыми полями?

Попытки поиска решения на данный момент

  • Насколько я понимаю, моя проблема заключается в том, чтобы установить для свойства CancelEventArgs' Cancel значение true, потому что оно "отрезает" остальную часть проверки. Таким образом, было бы неплохо найти способ не устанавливать это свойство на потом или найти способ обойти это. Но я не уверен, как это сделать.

  • Одной из моих первоначальных мыслей было то, что я мог бы решить эту проблему довольно легко, если бы только мог возвращать boolean из каждого проверяющего обработчика событий (однако я подозревал и с тех пор узнал, что я не могу этого сделать). Я вижу альтернативу возвращаемым значениям в обработчиках событий — передать изменяемое значение (например, само CancelEventArgs). Кажется, это может быть подходящим решением, однако я не уверен, как я могу сделать это сам...


person Eilidh    schedule 11.12.2014    source источник


Ответы (1)


Настройка e.Cancel = true - это проблема, конечно. Так что просто не делай этого. В целом это довольно неприятная особенность, делающая ввод данных очень модальным. Гораздо более дружественный подход состоит в том, чтобы предоставить пользователю полную свободу действий при вводе данных, вводя данные в порядке, который не обязательно совпадает с тем, который вы предполагали, когда устанавливали порядок табуляции.

Просто напишите небольшой вспомогательный метод, который упростит задачу. Например:

    private Control firstInvalidControl;

    private void SetValidation(object sender, bool ok, string errMsg) {
        var ctl = (Control)sender;
        if (ok) errorProvider1.SetError(ctl, "");
        else {
            if (firstInvalidControl == null) firstInvalidControl = ctl;
            errorProvider1.SetError(ctl, errMsg);
        }
    }

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

    private void OKButton_Click(object sender, EventArgs e) {
        firstInvalidControl = null;
        this.ValidateChildren();
        if (firstInvalidControl != null) firstInvalidControl.Focus();
        else {
            // Data is good, use it
            // ...                
        }
    }
person Hans Passant    schedule 15.12.2014
comment
Спасибо большое за помощь! Извиняюсь за то, что так долго не принимал его в качестве ответа - я был очень занят другими проектами, и у меня не было времени попробовать его реализовать. Отличное элегантное решение! - person Eilidh; 16.12.2014