5. Общее представление об интерфейсах привязки данных

Обзор Data Grid View

он обладает гораздо более широкими

DataGridView Является мощным, гибким, но в то же время простым в использовании элементом управления для представления табличных данных. Он обладает гораздо более широкими возможностями, чем DataGrid, Его проще настраивать и с ним проще работать. Соответствующим образом установив свойства привязки, вы можете предоставить сетке самостоятельно делать всю работу по представлению данных в табличной форме. Можно также явно взять в свои руки контроль над представлением данных, воспользовавшись новыми возможностями несвязанных столбцов и виртуального режима. Несвязанные столбцы позволяют задавать содержание ячеек в процессе их добавления к сетке. Виртуальный режим позволяет вам подождать с передачей значения, которое должна содержать ячейка, до тех пор, пока она не будет действительно отображена. Вы можете заставить сетку работать подобно электронной таблице, так что фокус взаимодействия и представления смещается с уровня строк или столбцов на уровень отдельной ячейки. Вы можете управлять форматированием и планировкой сетки с ювелирной точностью, просто установив несколько свойств элемента управления. Наконец, вы можете включать в сетку предопределенные типы столбцов и ячеек и даже совмещать в одной строке или одном столбце элементы управления различного типа. показан пример элемента управления DataGridView В действии и выделены некоторые его ключевые визуальные элементы. Вы можете видеть, что сетка воспринимает установленные визуальные стили Windows ХР; сетка выглядит во многом подобно другим элементам управления Windows Forms в. NET 2.0. Сетка состоит из столбцов и строк, пересечение столбца и строки является ячейкой. Ячейка является элементарной единицей представления в сетке, ее внешний вид и поведение можно настраивать в широких пределах, используя экспонируемые сеткой свойства и события. Имеются заголовочные ячейки для строк и столбцов, которые можно использовать для хранения контекста представленной в сетке информации. Эти заголовочные ячейки могут содержать графические символы, индицирующие различные режимы или функции сетки, такие, как сортировка, редактирование, добавление строки и выбор. Сетка может содержать ячейки многих различных типов и даже совмещать различные типы ячеек в одной колонке, если сетка не привязана к данным.

Форма для просмотра иерархических данных

прародительские данные представлены сеткой в

Показано приложение с двумя уровнями привязки «ведущий-детализация», что означает наличие трех каскадированных источников привязки. Прародительские данные представлены сеткой в верхней части формы, которая привязана к источнику привязки, чьим источником данных является таблица GrandParentSet В типизированном наборе данных, генерированном по схеме на рис. 4.2. Прародительская таблица, две ее дочерних таблицы-сиблинга и таблица-внук были заполнены примерными данными, чтобы продемонстрировать автоматическую фильтрацию в действии. Первая и вторая дочерние таблицы имеют внешние ключи, связывающие их с данными прародительской таблицы, а таблица-внук имеет внешние ключи, связывающие ее с первым сиблингом. При выборе строки в таблице GrandParentSet Таблицы-сиблинги обновляются так, чтобы показывать лишь строки, соотнесенные с текущей выбранной строкой в прародителе. Аналогичным образом, при выборе строки в первой таблице-сиб — линге таблица-внук обновляется, отображая только данные строк, относящихся к выбранной строке родителя.

Все это достигается каскадированием источников привязки. Код, организующий привязку, показан на

Метод InitData Программно заполняет набор данных несколькими строками на каждую таблицу, устанавливая значения внешних ключей от дочерних таблиц к родительским таблицам так, чтобы они образовали привязку «ведущий-детализация». Как легко видеть, для каждой сетки данных имеется отдельный источник привязки, и все они организованы, как описывалось выше. Источник привязки наивысшего уровня для всей родительской иерархии имеет источником данных таблицу GrandParentSet. Для первого и второго дочерних источников привязки источником данных является прародительский источник привязки, а в их свойстве DataMember Установлено имя отношения, связывающего дочернюю таблицу с родительской. Например, для первого сиблинга это отношение FK_GrandPa — Rentset FirstsiblingSet. Внучатый источник привязки устанавливается так, что его источником данных является первый дочерний источник привязки, а в его свойстве DataMember Установлено отношение FK_FirstSi — BlingSet_GrandChildSet. Аналогичный подход с каскадированием источников привязки можно использовать для привязки коллекций объектов, имеющих иерархическую структуру. Взгляните на определения объектов в листинге 4.3.

Набор данных custData загружается схемой XML

набор данных b custdata b

В этом коде набор данных CustData Загружается схемой XML, которая соответствует XML, показанному ранее. Набор данных CustData Передается конструктору для XmlDataDocument, И он будет инкапсулировать ссылку на этот набор данных вместо того, чтобы создавать свой собственный. Имея инкапсулированный набор данных с соответствующей схемой, вы можете загружать XML в XmlDataDocument, И набор данных будет заполнен данными XML из загруженного документа, соответствующего схеме. Схема SimpleCustomers. xsd была создана путем загрузки XML из листинга Г. 10 в редактор Visual Studio и выбора Generate Schema в меню XML.

Еще более простой подход — просто прочитать XML в XmlDataDocument Через свойство Dataset: Здесь используется конструктор XmlDataDocument По умолчанию, который не принимает в качестве параметра набор данных. Он создаст внутри себя пустой набор данных, для которого затем вызывается ReadXml С передачей пути к файлу данных XML. Инкапсулированный набор данных при чтении XML выведет из него схему, как вы уже видели ранее. Как только XML прочитан в XmlDataDocument, Он может рассматриваться как набор узлов XML и к нему можно обращаться посредством методов базового класса Xml Document, А также методов инкапсулированного набора данных. Теперь давайте займемся аспектом загрузки в XmlDataDocument Существующего набора данных, содержащего данные, в целях навигации по ним как данным XML. Это может вам потребоваться, если у вас есть сложный набор данных и вы хотите производить выбор или исполнять запросы по нескольким таблицам в этом наборе, либо если данные являются иерархическими и навигация в объектной модели XML будет в этой ситуации более осмысленной.

Обновление источников данных через механизмы привязки

при этом не имеет значения

Как вы видели в листинге 3.4, если элементы управления привязаны у вас к источнику данных, вы можете осуществить автоматическое обновление источника данных в памяти при изменениях в привязанных элементах управления. При этом не имеет значения, привязан ли источник к сетке или к индивидуальным элементам управления, допускающим модификацию данных, таким, как текстовые поля. Чтобы изменения в привязанных элементах управления передавались в нижележащий источник данных, последний должен поддерживать определенные интерфейсы. Эти интерфейсы и требования к их реализации описываются в главе 7, пока же мы сосредоточимся на использовании наборов данных, реализующих все интерфейсы, требуемые для простой и сложной привязки данных и для обновления набора данных изменениями, которые производятся в привязанных элементах управления.

Когда пользователь модифицирует значение в привязанном элементе управления, таком, как TextBox, Происходит несколько вещей. Во-первых, возбуждаются события самого элемента управления, связанные с воздействием на него пользователя. Обычно теми действиями, которые инициируют события, являются изменение пользователем значения в элементе управления, например, текста в элементе управления TextBox, И последующий переход фокуса ввода на другой элемент путем нажатия клавиши табуляции или щелчка мыши. Серия генерируемых при этом событий зависит от конкретного действия пользователя, от типа элемента управления, от того, какое именно свойство элемента изменено и куда переходит фокус ввода. В главе 10 обсуждаются еще вопросы верификации, но вкратце все сводится к этому: если элемент управления поддерживает привязку данных и позволяет редактировать представляемое значение, то любые вносимые пользователем изменения автоматически сбрасываются в привязанный источник данных, как только элемент управления теряет фокус ввода. Нет никакого дополнительного кода, который реализовывал бы это поведение, оно неотъемлемо от привязок, которые вы установили в первую очередь для отображения данных. Как только фокус ввода перемещается на другой элемент управления, все внесенные изменения записываются в источник данных, использованный для привязки данного элемента.

Построение нового специального элемента управления, привязанного к данным

однако иногда вам возможно придется

К настоящему моменту я представил примеры того, как специальный элемент управления производится от встроенного элемента Framework и как разрабатывается пользовательский элемент управления, содержащий другие элементы и экспонирующий интерфейс привязки данных. Однако иногда вам, возможно, придется строить специальные элементы управления, которые не следуют простым сценариям инкапсуляции существующих элементов Framework, и вы, возможно, захотите поддерживать в них привязку данных. Если вы сможете осуществить хотя бы инкапсуляцию источника привязки в качестве дочернего компонента вашего элемента управления, то вы можете оставить ему всю грубую работу по привязке данных, как вы видели в последнем примере с FilteredGrid. Этот элемент управления естественно поддерживает все те мириады форм коллекций, которые поддерживаются элементами управления Framework, просто благодаря использованию источника привязки для сортировки данных из любого места, представленного в форме источника данных и компонента данных. В том случае, когда вам будет необходимо более непосредственное участие в отображении вашего элемента управления и доступе к данным, к которым он привязан, вам, возможно, придется вообще отказаться от поддержки со стороны источника привязки и вернуться к самостоятельной работе с различными формами коллекций данных. Если вы это сделаете, одним из возможных подходов будет непосредственная работа со всеми различными типами интерфейсов, описанными в главе 7, выяснение того, имеете ли вы дело со списком, списком списков, списком списков списков и т. д., и самостоятельное получение информации о типах, и реализация функций поиска и сортировки. Но в классах Framework можно найти и другую поддержку помимо источников привязки, которая может отчасти избавить вас от этой неприятной работы, как вы увидите в следующем примере. Итак, для демонстрации того, что значит «быть поближе к земле» и как реализовать элемент управления, не полагающийся в своей привязке к данным на какие-либо элементы управления Framework, давайте сразу приступим к практическому примеру.