2. Работа с наборами типизированных данных

Отслеживание данных при помощи событий

в таблице показаны события имеющиеся

Еще одна важная возможность сценариев привязки данных, особенно когда имеет место развязка уровней, состоит в оповещении об изменениях в нижележащем источнике данных при помощи событий. В таблице показаны события, имеющиеся в BindingSource. Такие события, как PositionChanged, ListChanged И CurrentChanged, Вы можете использовать для управления привязкой данных или синхронизации других элементов управления на форме, которые не обязательно находятся в строгих родительско-дочерних отношениях, которые допускали бы управление посредством каскадирования источников привязки, как было описано ранее. Например, представьте, что на форме имеется привязанный к данным комбинированный список, и при выборе в нем нового значения требуется переключить на новый источник данных — другой источник привязки, который управляет привязкой другой группы элементов управления на форме. Допустим, комбинированный список содержит строки соединения или имена баз данных. Вы можете решить эту проблему при помощи события SelectedlndexChanged Комбинированного списка. Но что, если на форме имеется несколько элементов управления, которые могут изменить текущий источник данных? Благодаря событию CurrentChanged Источника привязки вы можете очень просто решить проблему на уровне источника привязки, вместо того чтобы решать ее на уровне элементов управления.

Вы можете также использовать эти события для синхронизации между коллекциями данных, которые не связаны отношением «ведущий-детализация». Это иллюстрируется листингом 4.7 , где событие CurrentChanged Обновляет отображение родительского элемента при выборе в коллекции дочерних объектов. Событие CurrentChanged Можно еще использовать для организации своего рода связи «ведущий-детализация» между коллекциями объектов, связанных отношением «многие-ко-многим», как будет показано далее в разделе «Синхронизация коллекций, связанных отношением многие-ко-многим» .

Несколько более сложное приложение

допустим вы строите приложение winfx

Приложение «Hello World» не особенно продвинет вас вперед в понимании объектной модели WinFx и того, как образуется приложение, поэтому давайте взглянем на чуть более сложный пример. Допустим, вы строите приложение WinFx, которое будет производить идентификацию и авторизацию для определения того, что разрешено пользователю, исходя из сведений о нем в специальной базе данных и известных ролей. Итак, вам нужно идентифицировать пользователя, так что потребуется окно для входа в приложение. Давайте закодируем окно WinFx, которое будет выглядеть, как показанный на рис. Б.1 примитивный диалог авторизации. Сначала код создает объект Window Для главного окна и устанавливает его свойства width, Height И Text. Ничего загадочного здесь не происходит; код напоминает тот, что записывает в свой файл кода конструктор Windows Forms для каждой создаваемой вами формы.

Затем создаются следующие элементы управления: Grid, Два Text — Block, Один TextBox, Один PasswordBox И Button. Каждый экземпляр создается с помощью конструктора по умолчанию, после чего устанавливаются некоторые свойства. Для элементов TextBlock В свойстве Text — Content Устанавливаются строки подсказки, ради которых они здесь и присутствуют — здесь они используются аналогично элементам управления Label В Windows Forms. Для свойств HorizontalAlignment И Vertical Alignment Устанавливается значение Center, чтобы элементы были правильно выровнены на форме. Для TextBox, PasswordBox И Button Устанавливается свойство Height; Для Button В свойстве Content Устанавливается строка, которая будет отображаться на поверхности кнопки, аналогично тому, как это было со свойством Text Элемента управления Button В Windows Forms.

Обработка событий верификации

b когда запускаются и запускаются

Каждый элемент управления Windows Forms экспонирует два события, Validating И Validated, Которые наследуются от базового класса Control. Когда запускаются и запускаются ли вообще эти события, зависит от назначения производного элемента управления, некоторых свойств контейнерного элемента управления, которому он принадлежит, и от того, какой программный код активируется в отношении верификации. Предполагается, что событие Validating Запускается немедленно по завершении ввода, но до того, как ввод будет принят как действительный. Событие Validated Запускается, когда ввод принимается как действительный. Скажем, вы хотите написать в форме авторизации некоторый код, который проверяет поле имени пользователя. Простой пример, который можно было бы написать для подтверждения того, что в поле было введено некоторое значение, подписывал бы на событие Validating Элемента управления TextBox, Принимающего имя пользователя, следующий обработчик: Этот код входит в форму, которая содержит элемент управления M UsernameTextBox, И вызывается ею, когда фокус переключается на какой-то другой элемент управления формы. Код вызывает метод IsNullOrEmpty Класса String Для проверки того, пусто ли текстовое поле. Если это так, он устанавливает свойство Cancel Аргумента CancelEventArgs Равным True. Установка этого аргумента является сигналом инфраструктуре верификации Windows Forms о неудачной верификации данного элемента управления, что умолчанию завершит процесс верификации. Значением Cancel По умолчанию является False, Которое позволяет процессу верификации продолжаться. Затем отображается панель сообщения, чтобы предоставить пользователю некоторую обратную связь, информирующую о проблеме.

Откатывайте транзакции явным образом

однако я рекомендую вам всегда

Если вы закрываете соединение, на котором начали транзакцию, и еще не вызвали для нее Commit, Произойдет автоматический откат транзакции. Однако я рекомендую вам всегда делать это явным образом, самостоятельно вызывая Rollback , Чтобы было ясно, где и когда происходит откат Поскольку соединение открывается в листинге Г.9 явным образом, в дополнение к Try-Cach, Как вы можете видеть, я обеспечил его закрытие в блоке Finally, Поэтому, что бы ни происходило, соединение будет закрыто перед тем, как я выйду из метода. Вы видите здесь еще пару моментов, которые еще не обсуждались — это методы ExecuteScalar И ExecuteNon — Query Объектов SqlCommand. Метод ExecuteScalar Удобен для запросов, которые возвращают в качестве результирующего набора единственную строку с единственным столбцом. Метод извлекает значение этого столбца и передает его в качестве своего возвращаемого значения. Оно возвращается как объектная ссылка, поэтому необходимо приведение к ожидаемому типу, как показано в листинге Г.9. Метод ExecuteNonQuery Предназначен для исполнения команд, от которых вы не ожидаете каких-либо возвращаемых строк, таких, как запросы обновления, удаления и вставки. Когда транзакция создана, вам нужно ассоциировать ее с любыми командами, которые вы собираетесь применять внутри области действия транзакции. После этого вы можете исполнять команды. Если все получится так, как вы ожидаете, вы должны вызвать Commit Для объекта транзакции, чтобы сделать постоянными все изменения, произведенные внутри транзакции. Если что-то происходит не так, вы должны вызвать Rollback Транзакции, чтобы предотвратить запись любых изменений, сделанных командами внутри нее. Наилучшим способом обеспечить такую модель поведения является блок Try-Catch, Как показано в листинге Г.9. Если вы в своем коде явно открываете соединение, всегда заключайте код, который открывает соединение и исполняет запросы, в Try-блок. За ним расположите блок Finally И в нем закройте соединение. Тогда, завершается ли метод нормально или в результате неперехваченного исключения, соединение все равно будет закрыто и освобождено для использования другими клиентами.

Элементы управления ComboBox

помимо способа отображения списка и

Элемент управления ComboBox Представляет список данных в виде выпадающего списка с текстовым полем, которое может использоваться либо для отражения текущего выбора, либо для того, чтобы позволить пользователю ввести новое значение. Помимо способа отображения списка и того факта, что вы можете сделать текущее выбранное значение редактируемым, элемент управления работает во много м подобно полю списка с единственным выбором, но занимает на экране гораздо меньше места. Как и поле списка, он поддерживает в свойстве Items Список элементов типа ComboBox.ObjectCollection, Который он использует для отображения списка и который вы можете при желании использовать для хранения более сложных объектов, чем просто текстовые строки. Будет ли текущий выбор редактируемым, определяется установкой свойства DropDownStyle. Как и в случае поля списка, вы при необходимости можете обрабатывать событие SelectedlndexChanged. В этом методе вы могли бы возвращать для представления в списке или других элементах управления имя заказчика, но определение класса Customer Могло бы содержать элементы для ID и любых других ассоциированных данных, которые нужны для обработки выбора заказчика. В тот момент, когда вам потребуется произвести эту обработку, вы можете определить текущий выбор из свойства Selectedltem, Которое возвращает ссылку на соответствующий объект Customer. Так как Selectedltem Имеет тип Object, Для доступа к действительной информации объекта вам потребуется привести эту ссылку к ожидаемому типу. Следующий код показывает это в действии для дочернего элемента управления ListBox На форме с именем M_CustomersListBox: Вы можете отслеживать изменения выбора элементов в списке при помощи события SelectedlndexChanged. Когда вы обрабатываете это событие, вы можете использовать свойство Selectedlndex, Чтобы получить индекс в списке для одиночного выбора, либо свойства Selectedltem Или Selectedltems, Чтобы получить объектную ссылку на выбранные элементы в списке. Свойство Selectedltems Используется в случае, если вы разрешаете выбор нескольких элементов в поле списка, устанавливая свойство SelectionMode Равным MultiSimple Или MultiExtended.