3. Общее представление о привязке данных в Windows Forms

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

использование элемента управления b splitter

Наконец, элемент управления SplitContainer Является заменой известного элемента управления Splitter, Входившего в. NET 1.0 и 1.1. Использование элемента управления Splitter Было весьма неочевидным, поскольку было основано на z-порядке элементов управления в коллекции. По соображениям обратной совместимости элемент управления Splitter Все еще доступен, но SplitContainer Гораздо проще и понятнее в использовании. Он предусматривает полоску разделителя и две панели по обе стороны от нее, которые могут служить в качестве контейнерных элементов управления для всего, что вы поместите по ту или другую сторону разделителя. Это улучшает поведение формы как во время проектирования, так и во время выполнения при создании интерфейсов с разделенным окном показывают простой образец приложения, которое демонстрирует действие этих трех элементов управления. В этом приложении на форму был добавлен элемент управления SplitContainer, На его левую панель был добавлен контейнер TableLayoutPanel, Состыкованный по центру, а на правую был добавлен контейнер FlowLayoutPanel И также состыкован по центру. В шесть ячеек табличной панели планировки были помещены две метки, два текстовых поля и две радиокнопки. В поточную панель планировки были помещены четыре элемента управления PictureBox. Когда выбирается радиокнопка English или German, метки-подсказки для текстовых полей в табличной панели планировки переключаются на соответствующий язык. В.18 показывает первоначальный вид запущенного приложения, где справа только четвертое изображение переносится в начало второго ряда. Метки в таблице слева примыкают к своим текстовым полям и максимально используют отведенное для них пространство. Когда я изменяю размер формы, делая ее более узкой, и переключаюсь на немецкий язык, вы можете видеть эффект этих действий в двух панелях планировки на рис. В. 19. Более длинный текст немецких подсказок автоматически изменяет размер меток. Табличная панель планировки имеет фиксированную ширину, и для левой панели ее родительского разделенного контейнера установлена фиксированная ширина, поэтому табличная панель планировки изменяет ширину столбца с текстовыми полями, чтобы дать место более длинным меткам.

Обновление базы данных при помощи наборов данных

что если вы модифицировали данные

До сих пор мы рассматривали только извлечение данных из базы данных. Что, если вы модифицировали данные и хотите сохранить эти изменения в базе данных? Оказывается, другой мощной возможностью класса DataSet Является его способность отслеживать изменения, производимые в данных, которые он содержит. Изменения производятся в трех формах. Вы можете Чтобы обрабатывать изменения, набор данных хранит две копии каждой строки и отслеживает для каждой строки свойство RowState, Которое может принимать значения из перечисления DataRowState. Когда вы впервые извлекаете набор строк из базы данных, они добавляются к своей таблице со значением RowState, Равным Unchanged. Когда вы модифицируете значение столбца в существующей строке, ее состояние устанавливается в Modified. Когда вы добавляете новую строку или удаляете существующую, состояние строки будет помечено соответственно как Added Или Deleted. И если вы создаете для таблицы новую строку, но еще не добавили ее к коллекции Rows, Ее состоянием будет Detached. Состояние строки позволяет адаптеру данных определить, какие строки должны быть использованы для выполнения вставок, обновлений или удалений в таблице базы данных. Когда вы изменяете значения существующей строки, текущие значения для столбцов сохраняются в одной копии строки, но исходные значения этой строки на тот момент, когда данные были извлечены, также сохраняются во второй ее копии. Это позволяет использовать исходные значения для контроля оптимистической конкуренции. Значения Rowstate и их смысл описываются в таблице Г.2. Вы обновляете базу данных набором данных, используя адаптер данных. Имейте в виду, что когда я говорю «обновляете», я имею в виду исполнение любых необходимых запросов на обновление, вставку или удаление. Постарайтесь не смешивать это со специфическими SQL-запросами UPDATE, которые воздействуют только на модифицированные строки и являются лишь одной из трех форм «обновлений».

Команды которые вы ассоциируете с адаптером данных

в случае большого набора данных

В любом случае команды, которые вы ассоциируете с адаптером данных, будут исполняться по одной для каждой строки в наборе данных, которая требует обновления. В случае большого набора данных с большим числом изменений это может привести к массе обратных пересылок по сети к базе данных. Для решения этой проблемы в ADO. NET 2.0 класс SqlDataAdapter Имеет механизм пакетного обновления, который будет группировать все запросы и сразу посылать их базе данных в одном или нескольких пакетах. Чтобы воспользоваться этой возможностью, вы устанавливаете свойство UpdateBatchSize В SqlDataAdapter Некоторым значением, отличным от 1 . Если вы устанавливаете значение О, то все обновления будут сгруппированы в один пакет. Если устанавливается некоторое положительное значение, большее 1, адаптер данных будет набирать пакеты с указанным количеством запросов и посылать их до тех пор, пока все обновления не будут завершены. Однако следует иметь в виду, что когда вы применяете такой подход и посылаете пакет запросов на обновление, в SQL Server они будут исполняться как одна транзакция. Поэтому, если какой-либо строке в пакете не удастся выполнить свое обновление, потерпит неудачу весь пакет. Чтобы автоматически формулировать запросы обновления для непосредственной работы с таблицами, имеется класс SqlCommandBuilder, Который может исследовать команду выбора, используемую в адаптере данных, и динамически генерировать за вас команды вставки, обновления и удаления. Затем он заполнит командные свойства адаптера соответствующими запросами. Построитель команд хорошо работает для простых наборов данных, которые содержат таблицы, генерированные операторами SELECT для одиночной таблицы с ограничением первичного ключа. Автоматическое создание команд происходит при конструировании объекта построителя команд с передачей адаптера данных, для которого нужно создать команды. Никакие его методы или свойства вы не будете на самом деле вызывать непосредственно.

Верификация ввода данных и обработка ошибок

хотя я откладывал рассмотрение этой

Верификация ввода данных и обработка ошибок являются важной частью любого приложения для данных. Хотя я откладывал рассмотрение этой темы до последней главы, вы не должны откладывать продумывание того, что делать с ошибками, до конца своего проекта. Вы должны разрабатывать и интегрировать код обработки ошибок на протяжении всего проекта. Windows Forms Validation Framework предлагает превосходный отправной пункт и механизмы для единообразной обработки верификации ввода, дружественной в отношении пользователя. Взяв за основу эту инфраструктуру, вы можете добавлять специальные верификаторы, избавляющие от необходимости писать один и тот же код для обработки требуемых полей, сравнений, проверок диапазона и шаблонов ввода. Ошибки верификации не являются единственным видом ошибок, которые могут происходить в ваших приложениях, поэтому нужно быть готовым к тому, что вам придется иметь дело с ошибками параллелизма данных, ошибками форматирования и анализа и другими видами ошибок. Ваши рабочие объекты сами могут содержать проверку на ошибки, и если вы привязываете эти объекты к элементам управления, то захотите единообразно передавать информацию об этих ошибках наверх при помощи интерфейса IDataErrorlnfo.

Вот ключевые выдержки из этой главы: Обрабатывайте событие Validating, И если вы обнаруживаете ошибку верификации, устанавливайте в True Свойство Cancel Аргумента события.

Используйте элемент управления ErrorProvider, Чтобы стандартным образом, по месту предоставлять пользователю информацию об ошибке. Ознакомьтесь с библиотеками верифицирующих элементов управления, созданными Майклом Вайнхардтом и Билли Холлисом, посмотрев их статьи в «MSDN Online» об утилизируемых элементах управления для верификации требуемых полей, проверок диапазона, сравнений полей и регулярных выражений. Реализуйте в специальных рабочих объектах интерфейс IDataErrorlnfo, Чтобы предоставлять привязанным элементам управления развернутую информацию об ошибках.

Организация транзакций в System. Transact ions

net был разработан совершенно новый

В. NET 2.0 был разработан совершенно новый подход к написанию транзакционного кода, реализованный в пространстве имен System.Transactions. При помощи классов, определенных в этом пространстве имен, вы можете теперь в своем коде очень просто начинать или соединять транзакции, не привязываясь непосредственно к транзакционным возможностям базы данных или какого-то другого менеджера ресурсов транзакции. Транзакции, создаваемые посредством классов System.Transactions, Могут быть как облегченными транзакциями с единственным менеджером ресурсов, таким, как одиночная база данных SQL Server 2005, так и распределенными транзакциями, в который участвует несколько менеджеров ресурсов, как в базе данных SQL 2000, базе данных Oracle и очереди сообщений MSMQ. Другой замечательной особенностью новых транзакционных средств является то, что транзакция будет автоматически переводить себя из облегченной транзакции в распределенную, если она видит, что в области действия транзакции происходит обращение к новому менеджеру ресурсов, который требует распределенной транзакции, поэтому вам не нужно беспокоиться в своем коде относительно корректного использования различных моделей. Чтобы использовать System.Transactions, Вы прежде всего должны добавить в свой проект ссылку на сборку System. Transactions. dll из. NET Framework. Затем нужно включить пространство имен System.Transactions В файлы кода, где вы будете его использовать. Когда вам нужно будет исполнить некоторый код внутри транзакции, вы устанавливаете транзакционную область действия, создавая экземпляр класса Transac — TionScope. Затем вы исполняете код, который должен быть транзакционным, и если все проходит успешно, вызываете метод Complete Объекта TransactionScope. Транзакция на самом деле не будет зафиксирована до тех пор, пока вы не уничтожите объект области действия, а если вызвать Dispose Без предварительного вызова Complete Объекта области действия, транзакция будет прервана.

Проще всего проделать все это в C# при помощи блока Using. Когда вы организуете блок Using В С#, вы передаете предложению Using Объектную ссылку, являющуюся уничтожаемым объектом. Когда происходит выход из блока Using, Для объекта автоматически будет вызван Dispose, Даже если транслируется исключение. Это происходит потому, что генерируемый компилятором код для блока Using Включает блок Try-Finally, И в блоке Finally Вызывается Dispose Для аргумента предложения Using.