4.5.2. Проверка на уровне формы
Проверка данных на уровне формы позволяет одним алгоритмом проанализировать содержимое всех ее полей. Для этого часто применяют процедуру, которая вызывается при уходе пользователя с текущей формы; другой способ – обработка некоторого события на уровне формы.
Рассмотрим пример метода, проверяющего на уровне формы. По щелчку кнопки btnValidate этот метод проверяет, все ли текстовые поля формы заполнены. Если обнаружено пустое поле, метод передает ему фокус.
private void btnValidate_Click (object sender, EventArgs e)
{
foreach (Control aControl in this.Controls)
{
if ( aControl is TextBox && aControl.Text == "") { aControl.Focus (); return; }
}
}
Обработка клавиатурных событий на уровне формы – более сложная методика. Она позволяет централизованно управлять вводом данных в совокупность полей формы. Можно написать метод, активирующий командные кнопки только после заполнения всех полей и выполняющий определенные действия в зависимости от того, какие клавиши нажимаются.
По умолчанию форма генерирует события клавиатуры KeyPress, KeyDown и KeyUp только в случае, только если на ней нет активированных или видимых элементов управления. В противном случае эти события генерирует элемент управления, имеющий фокус. Чтобы заставить форму автоматически генерировать события клавиатуры, необходимо установить ее свойство KeyPreview в true. В результате форма будет генерировать эти события прежде элемента управления, получившего фокус.
4.5.3. Оповещение пользователя об ошибках ввода
Если пользователь ввел в поле недопустимое значение, необходимо сообщить ему об этом и дать возможность исправить ошибку. Если ошибка очевидна, то можно ограничиться звуковым сигналом (заметим, что в ранних версиях .NET для этого нет встроенных методов, их можно программировать). Привлечь внимание пользователя можно и по-другому, изменив цвет фона или текста элемента управления (при помощи его свойств BackColor и ForeColor соответственно).
Для вывода более информативного описания ошибки можно воспользоваться методом MessageBox.Show, отображающим небольшое модальное окно с заданным сообщением:
MessageBox.Show ("Вы ввели неверное значение " + aControl.Text);
aControl.Focus ();
Удобный способ оповещения пользователя об ошибках ввода предоставляет компонент ErrorProvider. Он позволяет для любого элемента управления задать текст сообщения об ошибке. Тогда рядом с данным элементом появляется предупреждающий значок, а если навести на этот значок указатель мыши, то отображается всплывающая подсказка с подготовленным сообщением.
Компонент ErrorProvider относится к провайдерам дополнительных свойств и расположен в секции Windows Forms панели Toolbox. Задать элементу сообщение об ошибке можно сразу в дизайнере посредством окна Properties либо программно (по мере необходимости, что более естественно) методом SetError компонента ErrorProvider. Его параметрами являются элемент управления (ссылка на него) и текст сообщения. Например:
myErrorProvider.SetError (nameTextBox, "Имя не может быть пустым!");
Некоторые свойства компонента ErrorProvider определяют способ отображения сообщения об ошибке. Свойство Icon задает значок ошибки. Одна форма может содержать несколько экземпляров ErrorProvider (например, ошибки и предупреждения) с различными значками. Другое свойство этого компонента – BlinkStyle – заставляет значок мигать, частоту мигания определяет свойство BlinkRate.
Резюме
На уровне формы поля проверяются централизованно, на уровне поля – индивидуально по мере заполнения.
У элемента TextBox есть свойства времени разработки, определяющие допустимые значения: MaxLength, PasswordChar, ReadOnly, MultiLine.
Клавиатурные события (KeyDown, KeyUp, KeyPress) позволяют проверять символы, вводимые при нажатии клавиш и их сочетаний. Эти события генерируются текущим элементом управления. Если свойство KeyPreview формы установлено в true, то первой их генерирует форма.
Для проверки вводимых данных обычно применяется событие Validating. Оно генерируется перед потерей фокуса элементом управления, если у элемента управления, который получает фокус следующим, свойство CausesValidation установлено в true.
При помощи компонента ErrorProvider элементу можно назначить текст сообщения и значок для оповещения об ошибке ввода. Для отображения сообщений об ошибках во время выполнения применяется метод SetError.
5. Объектно-ориентированное программирование
5.1. Общие принципы
C# наряду с другими .NET-языками является объектно-ориентированным. Имеющиеся в языке объектно-ориентированные возможности образуют его объектную модель. Представление сущностей реального мира посредством программных объектов называется абстрагированием (abstraction).
Итак, программирование в .NET-окружении основано на объектах. Объект – это программная конструкция, содержащая набор логически связанных данных и операций. Объекты предоставляют некоторую функциональность другим компонентам, скрывая от них свое внутреннее устройство. Объекты создаются на основе шаблонов, называемых классами. Библиотека базовых классов .NET содержит набор готовых классов, которые можно применять для создания объектов в приложениях. Кроме того, среда Visual Studio позволяет разрабатывать новые классы на основе имеющихся. При создании объекта в памяти создается экземпляр соответствующего класса. Это можно сделать с помощью ключевого слова new:
Widget myWidget = new Widget ( );
Объекты состоят из членов четырех видов: свойства, поля, методы и события. Поля и свойства содержат данные объекта, методы определяют действия, которые объект способен выполнять, а события представляют уведомления, которые объект может получать или отправлять другим объектам, если происходит нечто важное.
Рассмотрим, например, объект Автомобиль. Его свойства и поля Цвет, Модель, Возраст, Расход_топлива представляют данные, описывающие состояние объекта. Методы Нажать_акселератор, Переключить_передачу или Повернуть_руль формируют поведение объекта. Событие представляет собой уведомление о важных происшествиях. Для объекта Автомобиль необходимо, чтобы объект Двигатель уведомлял его о событии Перегрев, а взаимодействие с объектом Дерево должно вызвать событие Столкновение.
Из примера следует, что сложные объекты способны содержать вложенные объекты и открывать к ним доступ, как к своим членам. Например, элемент управления TextBox поддерживает свойство Font, которое представляет собой объект типа Font. Аналогично любой экземпляр класса Form содержит и предоставляет набор Controls, в который входят все элементы управления, размещенные на форме.
В основе программирования с использованием классов лежат три основных принципа: инкапсуляция, полиморфизм и наследование.
Инкапсуляция состоит в объединении логически связанных данных и операций в общем контейнере, а также отделении (и сокрытии) реализации объекта от его интерфейса. Приложение взаимодействует с объектом через его интерфейс, состоящий из открытых свойств и методов. При неизменном интерфейсе оно сохраняет способность к взаимодействию с объектом, даже если в его новой версии реализация полностью изменится. Интерфейс не должен открывать доступ к внутренним данным объекта, поэтому поля с внутренними данными объекта редко объявляются с модификатором public.
Благодаря полиморфизму, одни и те же открытые интерфейсы можно по-разному реализовать в разных классах. Другими словами, полиморфизм позволяет вызывать методы и свойства объекта независимо от их реализации. Например, объект Водитель взаимодействует с объектом Автомобиль через открытый интерфейс. Если другой объект, например Грузовик или Спортивный_автомобилъ, поддерживает тот же открытый интерфейс, то объект Водитель сможет взаимодействовать и с ними, невзирая на различия в реализации интерфейса. Существуют два основных подхода к реализации полиморфизма: через интерфейсы и через наследование.
Интерфейс – соглашение, определяющее поведение объекта. Интерфейс определяет список членов класса (свойств и методов), но ничего не говорит об их реализации. В объекте допустимо реализовать несколько интерфейсов, а один и тот же интерфейс можно реализовать в разных классах.
Наследование позволяет конструировать новые классы на основе имеющихся классов. Они называются производными (или дочерними) по отношению к базовым. В объектной модели .NET у каждого класса может быть только один непосредственный базовый класс. Производный класс получает тот же набор членов, к которому можно добавлять новые члены. Можно также изменить реализацию членов, унаследованную от базового класса, переопределив их. Представители производных классов могут взаимодействовать с другими объектами как экземпляры базового класса.
Резюме
Представление объектов реального мира программными конструкциями называется абстрагированием. Экземпляры классов воспроизводят характеристики объектов реального мира посредством их членов.
Классы аналогичны «чертежам» объектов. При создании объекта в памяти создается копия данных, определенных в классе, и устанавливаются начальные значения для членов-переменных. Класс – это шаблон, на основе которого можно создать сколько угодно объектов этого класса.
Инкапсуляция – один из фундаментальных принципов ООП. Объект должен содержать необходимые ему данные и код для манипулирования ими. Данные объекта не должны быть доступными другим объектам. Интерфейсы предоставляют доступ только к свойствам и методам.
Полиморфизм позволяет по-разному реализовать один и тот же открытый интерфейс в разных объектах. В C# существуют два основных способа реализации полиморфизма: через интерфейсы и наследование.