НА ЗАМЕТКУ
При выполнении приложения на платформе .NET Compact Framework 1.1 в случае установки значения свойства Text элемента управления TextBox программным путем событие TextChanged в действительности запускается дважды.
Выполнение того же кода на настольном компьютере сопровождается только однократным запуском указанного события. Вероятно, поведение последующих версий NET Compact Framework будет изменено таким образом, чтобы оно совпадало с поведением .NET Framework (однократный запуск события). События — коварная вещь. Будьте очень внимательны в своих предположениях относительно того как и когда запускаются события.
int m_eventTriggerCount;
private void textBox1_TextChanged(object sender, System.EventArgs e) {
m_eventTriggerCount++;
//Обновить надпись для отображения количества событий
label1.Text = "Events: #" + m_eventTriggerCount.ToString;
//Внести каждое событие в список
listBox1.Items.Add(m_eventTriggerCount.ToString + textBox1.Text);
}
private void button1_Click(object sender, System.EventArgs e) {
//Запускает событие TextChanged так же,
//как если бы текст был введен пользователем
textBox1.Text = "Hello World";
}
Как видно из листинга 11.3, программная установка свойства Text элемента управления TextBox запускает тот же код обработки событий, который запускался бы при вводе текста пользователем. В зависимости от того, какие допущения вами сделаны, результаты могут как совпадать, так и не совпадать с ожидаемыми. Программисты часто пишут коды, предназначенные для заполнения пользовательских интерфейсов данными после их извлечения из внешнего источника. При этом устанавливаются свойства Checked переключателей RadioButton и флажков CheckBox, заполняются значения текстовых полей TextBox, заполняются элементами списки ListBox и ComboBox и так далее. Во многих случаях программисты предполагают, что выполнение всех этих установочных действий не приводит к запуску событий пользовательского интерфейса. Обычно в намерения программиста не входит, чтобы эти события запускались, поскольку пользовательский интерфейс всего лишь подготавливается к тому, чтобы пользователь мог им воспользоваться. Очень часто программисты, которые разрабатывают приложение, хотят, чтобы код обработки событий приложения запускался лишь тогда, когда происходит внешнее событие, например, поступает сигнал таймера, пользователь выполняет щелчок на кнопке или вводит текст в элемент управления и тому подобное.
Сложность работы с кодами, управляемыми событиями, связана с тем, что невозможно заранее знать, когда именно будет вызван код того или иного обработчика события. Просматривая исходный код приложения, вы можете точно сказать, когда вызываются библиотечные функции или другие части кода приложения, но ничто не укажет вам на то, когда именно среда выполнения запустит событие. По этой причине большинство разработчиков просто делают относительно этого некоторые предположения, которые даже не удосуживаются тщательно проверять. Кроме того, по мере увеличения объема приложения за счет дальнейшего добавления пользовательского кода и соответствующего усложнения его внутренней структуры в нем появляется все больше кода, предназначенного для генерации и обработки событий пользовательского интерфейса; из-за этого также могут возникать весьма тонкие взаимодействия, обнаружить которые простым просмотром исходного текста кода очень трудно. Так, код, реагирующий на выбор элемента в списке ListBox, может запускать код, инициирующий обновление свойств элементов управления CheckBox и TextBox, как показано в приведенном ниже примере:
textboxUserName.Text = selectedRecord.Username;