Опубликован: 11.09.2006 | Уровень: специалист | Доступ: свободно
Лекция 3:

Работа с элементами управления (продолжение)

Проверка вводимых значений. События 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).

Проверка значений поля PIN2. Текст сообщения, появляющегося при ошибке, был изменен

Рис. 3.9. Проверка значений поля PIN2. Текст сообщения, появляющегося при ошибке, был изменен

Событие 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.10. Иконка уведомления элемента ErrorProvider

Некоторые свойства элемента ErrorProvider, отвечающие за внешний вид иконки, приводятся в таблице 3.2.

Таблица 3.2. Свойства ErrorProvider
Свойство Описание Значение по умолчанию
Blinkrate Частота мерцания в миллисекундах 250
BlinkStyle Стиль появления иконки. Возможны следующие варианты: BlinkIfDifferentError – иконка появляется при ошибке, мерцает несколько раз и останавливается;AlwaysBlink – при ошибке иконка мерцает постоянно;NeverBlink – иконка появляется, но не мерцает BlinkIfDifferentError
Icon Изображение иконки. Можно использовать другие файлы иконок (.ico) ICO(Icon)

На диске, прилагаемом к книге, вы найдете приложение ErrorProvider (Code\Glava3\ ErrorProvider).

Создание пользовательских (композитных) элементов управления. Элемент управления NumericUpDown

Одинаковая группа элементов с привязанными обработчиками может требоваться в нескольких частях большого приложения или даже нескольких приложений. Например, программы Microsoft Word и Excel содержат много одинаковых связанных элементов — панели инструментов, окна настроек, группы меню. Среда Visual Studio .NET предоставляет возможность создания функциональных блоков, состоящих из многих элементов; применение этих блоков позволяет значительно ускорить разработку приложений. Создаем новый проект в Visual Studio .NET — на этот раз выбираем шаблон Windows Control Library (рис. 3.11).

Проект UserInput, шаблон проекта — Windows Control Library

Рис. 3.11. Проект UserInput, шаблон проекта — Windows Control Library

Появляется форма без границ, представляющая собой основу, на которой будут располагаться элементы. В принципе, можно разрабатывать функциональность и проверять код, компилируя проект при помощи пункта меню 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):

Проект UserInput, расположение элементов управления на форме

Рис. 3.12. Проект UserInput, расположение элементов управления на форме

Две надписи будут статичными, а на третью будут выводиться сообщения при ошибках. Установим свойству Name этой надписи значение lbloutput. Устанавливаем следующие значения текстового поля, элементов ErrorProvider и NumericUpDown:

textBox1, свойство Значение
Name txtName
Text
numericUpDown1, свойство Значение
Name numUDAge
Maximum 100
Minimum 1
Value 25
errorProvider1, свойство Значение
BlinkStyle AlwaysBlink
Icon ICOCode\Glava3\UserInput\Icon\none.ico

Проверять ввод значений будем в текстовом поле и элементе 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):

Готовое приложение UserInput

Рис. 3.13. Готовое приложение UserInput

Преобразуем теперь проект в композитный элемент, скомпилируем его в режиме Build (Ctrl+Shift+B) и закроем.

На диске, прилагаемом к книге, вы найдете приложение UserInput (Code\Glava3\UserInput).

Елена Дьяконова
Елена Дьяконова

При нажатии на Сумма в примере ArbitraryMethod из Лекция 7, VS 2013 выдается ошибка: 

Необработанное исключение типа "System.InvalidOperationException" в System.Windows.Forms.dll

Дополнительные сведения: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления "lblResult" не из того потока, в котором он был создан.

Затем:

Необработанное исключение типа "System.InvalidOperationException" в mscorlib.dll

Дополнительные сведения: Для каждой асинхронной операции метод EndInvoke может вызываться только один раз.

Александр Сороколет
Александр Сороколет

Свойство WindowState формы blank Maximized. Не открывается почемуто на всё окно, а вот если последующую форму бланк открыть уже на макс открывается :-/