При нажатии на Сумма в примере ArbitraryMethod из Лекция 7, VS 2013 выдается ошибка: Необработанное исключение типа "System.InvalidOperationException" в System.Windows.Forms.dll Дополнительные сведения: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления "lblResult" не из того потока, в котором он был создан. Затем: Необработанное исключение типа "System.InvalidOperationException" в mscorlib.dll Дополнительные сведения: Для каждой асинхронной операции метод EndInvoke может вызываться только один раз. |
Работа с элементами управления (продолжение)
Проверка вводимых значений. События KeyPress и Validating элемента управления TextBox
При внесении значений параметров пользователем или заполнении регистрационной формы требуется проверять вводимый текст по заданным критериям. Например, регистрационный номер не должен содержать букв. Рассмотрим проверку, которую можно осуществлять, используя встроенные события текстового поля. Скопируйте папку приложения RegistrationForm и дайте ей новое название — ValidatingInput. Запускаем проект. Текстовым полям, находящимся напротив надписей Name и PIN, задаем названия (значения свойства Name) — txtName и txtPIN соответственно. Располагаем на форме новую надпись lbloutput – на нее будут выводиться сообщения об ошибках, поэтому значение свойства Text оставляем пустым. Выделяем поочередно текстовые поля и в окне Properties создаем обработчиков события KeyPress, возникающего при нажатии любой клавиши в поле. Для элемента txtName недопустимыми значениями будут цифры:
private void txtName_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) { if (char.IsDigit(e.KeyChar) ) { e.Handled = true; lbloutput.Text = "Поле Name не может содержать цифры"; } }
Для элемента txtPIN, наоборот, недопустимыми значениями будут буквы:
private void txtPIN_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) { if (!char.IsDigit(e.KeyChar) ) { e.Handled = true; lbloutput.Text ="Поле PIN не может содержать буквы"; } }
Запускаем приложение. При попытке ввести недопустимое значение в одно из полей появляется сообщение, а клавиатура блокируется. Даже стандартная кнопка закрытия формы не работает, пока не будут внесены исправления.
Для текстового поля, появляющегося при установке галочки в чекбоксе "Расширенные возможности", необходимо вручную определить событие KeyPress:
private void checkBox1_CheckedChanged(object sender, System.EventArgs e) { … txt.KeyPress+= new System.Windows.Forms.KeyPressEventHandler(this.txtPIN_KeyPress); }
Запускаем приложение. Теперь проверяются значения и в появляющемся поле PIN2 (рис. 3.9).
Событие KeyPress блокирует часть клавиатуры. Другим способом проверки является событие Validating, позволяющее работать с клавиатурой, но блокирующее другие действия пользователя. Закомментируем обработчик txtPIN_KeyPress, переключимся в режим дизайна формы и в окне Properties элемента txtPIN создадим обработчик события Validating:
private void txtPIN_Validating(object sender, System.ComponentModel.CancelEventArgs e) { if(txtPIN.Text =="") { e.Cancel=false; } else { try { double.Parse(txtPIN.Text); e.Cancel = false; } catch { e.Cancel = true; lbloutput.Text ="Поле PIN не может содержать буквы"; } } }
Для проверки введенное значение преобразуется к типу double — текст сгенерирует исключение. Запускаем приложение. При переключении фокуса ввода или нажатии на кнопку "регистрация" происходит событие Validating.
На диске, прилагаемом к книге, вы найдете приложение ValidatingInput (Code\Glava3\ ValidatingInput).
Проверка вводимых значений. Элемент управления ErrorProvider
Элемент управления ErrorProvider удобно применять, когда нужно выводить небольшую иконку в случае ошибки ввода. Скопируйте папку RegistrationForm и назовите ее ErrorProvider. Запускаем проект, в режиме дизайна из окна ToolBox перетаскиваем на форму элемент управления ErrorProvider. Переходим в код формы. Изменим обработчиков txtName_KeyPress и txtPIN_KeyPress следующим образом:
private void txtName_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) { if (char.IsDigit(e.KeyChar) ) { errorProvider1.SetError(txtName, "Must be letter"); lbloutput.Text = "Поле Name не может содержать цифры"; } } private void txtPIN_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) { if (!char.IsDigit(e.KeyChar) ) { errorProvider1.SetError(txtPIN, "Must be number"); lbloutput.Text ="Поля PIN и PIN2 не могут содержать буквы"; } }
Вторым параметром в методе SetError передается строка с описанием ошибки, которая может быть выведена на форму. Мы воспользуемся, однако, выводом сообщения в надписи lbloutput. Запускаем приложение. При ошибке появляется мигающая иконка уведомления (рис. 3.10):
Некоторые свойства элемента ErrorProvider, отвечающие за внешний вид иконки, приводятся в таблице 3.2.
Свойство | Описание | Значение по умолчанию |
---|---|---|
Blinkrate | Частота мерцания в миллисекундах | 250 |
BlinkStyle | Стиль появления иконки. Возможны следующие варианты: BlinkIfDifferentError – иконка появляется при ошибке, мерцает несколько раз и останавливается;AlwaysBlink – при ошибке иконка мерцает постоянно;NeverBlink – иконка появляется, но не мерцает | BlinkIfDifferentError |
Icon | Изображение иконки. Можно использовать другие файлы иконок (.ico) | (Icon) |
На диске, прилагаемом к книге, вы найдете приложение ErrorProvider (Code\Glava3\ ErrorProvider).
Создание пользовательских (композитных) элементов управления. Элемент управления NumericUpDown
Одинаковая группа элементов с привязанными обработчиками может требоваться в нескольких частях большого приложения или даже нескольких приложений. Например, программы Microsoft Word и Excel содержат много одинаковых связанных элементов — панели инструментов, окна настроек, группы меню. Среда Visual Studio .NET предоставляет возможность создания функциональных блоков, состоящих из многих элементов; применение этих блоков позволяет значительно ускорить разработку приложений. Создаем новый проект в Visual Studio .NET — на этот раз выбираем шаблон Windows Control Library (рис. 3.11).
Появляется форма без границ, представляющая собой основу, на которой будут располагаться элементы. В принципе, можно разрабатывать функциональность и проверять код, компилируя проект при помощи пункта меню Build (Ctrl+Shift+B). Однако при этом мы не увидим результатов работы композитного элемента, пока не добавим его на другую форму. Поэтому на время разработки переделаем проект в Windows-приложение, а потом, когда все будет готово, вернем ему исходный вид. При попытке запустить приложение появляется сообщение "A project with an Output Type of Class Library cannot be started directly" (Проект с выходным типом Class Library (Библиотека классов) не может быть запущен непосредственно). В окне Solution Explorer щелкаем правой кнопкой на имени проекта UserInput и в появившемся контекстном меню выбираем Properties. В окне UserInput Property Pages изменяем значение свойства OutputType на Windows Application. Снова запускаем приложение. Появляется ошибка — приложение не содержит точки входа:
Program 'D:\Uchebnik\Code\Glava3\UserInput\obj\Debug \UserInput.exe' does not have an entry point defined
Добавляем метод Main в класс формы:
[STAThread] static void Main() { Application.Run(new UserControl1()); }
Снова запускаем приложение — появляются две ошибки:
1.D:\Uchebnik\Code\Glava3\UserInput\UserControl1.cs(44): The best overloaded method match for'System.Windows.Forms.Application.Run(System.Windows.Forms.Form)' has some invalid arguments 2.D:\Uchebnik\Code\Glava3\UserInput\UserControl1.cs(44): Argument '1': cannot convert from 'UserInput.UserControl1' to 'System.Windows.Forms.Form'
Класс UserControl1 наследует от класса UserControl:
public class UserControl1 : System.Windows.Forms.UserControl
Обычный класс Windows-приложения наследует от класса Form:
public class Form1 : System.Windows.Forms.Form
Закомментируем наследование этого класса (не удалим!) и добавим наследование от класса Form:
public class UserControl1 : System.Windows.Forms.Form
Вид формы в режиме дизайна изменится на стандартный шаблон — с заголовком, который теперь запускается. Итак, для преобразования композитной формы мы изменили выходной тип проекта, добавили метод Main и изменили наследование классов. Проделав обратные шаги, мы можем получить снова композитную форму или преобразовать обычную форму в композитную.
Займемся теперь созданием функциональности. Добавляем на форму три надписи, текстовое поле, ErrorProvider и элемент управления NumericUpDown (рис. 3.12):
Две надписи будут статичными, а на третью будут выводиться сообщения при ошибках. Установим свойству Name этой надписи значение lbloutput. Устанавливаем следующие значения текстового поля, элементов ErrorProvider и NumericUpDown:
Проверять ввод значений будем в текстовом поле и элементе NumericUpDown. В окне Properties создаем обработчиков событий Validated элементов:
private void txtName_Validated(object sender, System.EventArgs e) { if(nameValid()) { // Все правильно, удаляем сообщение с надписи errorProvider1.SetError(txtName, ""); } else { //Поле не заполнено — выводим сообщение errorProvider1.SetError(txtName, "Name is required."); lbloutput.Text = "Введите имя!"; } } private void numUDAge_Validated(object sender, System.EventArgs e) { if (ageLess()) { // Введенное значение меньше 25 errorProvider1.SetError(numUDAge, "Age not old enough"); lbloutput.Text = "Введите значение, большее или равное 25"; } else if (ageMore()) { /// Введенное значение больше 25 errorProvider1.SetError(numUDAge, "Age is too old"); lbloutput.Text = "Введите значение, меньшее или равное 65"; } else { // Все правильно, удаляем сообщение с надписи errorProvider1.SetError(numUDAge, ""); } }Листинг 3.4.
Осталось добавить методы, в которых проверяются заданные значения:
private bool nameValid() { // Проверяем заполнение текствого поля return ( txtName.Text.Length > 0); } private bool ageLess() { //Возраст меньше 25 return (numUDAge.Value < 25); } private bool ageMore() { //Возраст больше 65 return (numUDAge.Value > 65 ); }
Запускаем приложение. При ошибках иконка мигает беспрерывно, в случае ее исправления сообщение исчезает (рис. 3.13):
Преобразуем теперь проект в композитный элемент, скомпилируем его в режиме Build (Ctrl+Shift+B) и закроем.
На диске, прилагаемом к книге, вы найдете приложение UserInput (Code\Glava3\UserInput).