4. Привязка объектов контроля к источникам данных

Навигация в XML-документе

однако все типы xml документов

Каждый из различных типов XML-документов имеет набор специализированных методов навигации, зависящих от специфической объектной модели, которую они экспонируют. Однако все типы XML-документов позволяют вам получить для документа XPathNavigator, Который дает возможность выдавать запросы и осуществлять навигацию, единообразно используя предпочтительную объектную модель для работы с XML в. NET. В предыдущем разделе вы увидели, как выполнять запросы к документу, возвращая итератор, который вы могли использовать для прохода по каждому из узлов, отвечавших запросу, и выполнения их обработки. Для работы с узлом вы получали из свойства Current Итератора ссылку на узел типа XPathNavigator. Когда у вас будет XPathNavigator На некоторый узел, вам часто потребуется выполнить какую-то навигацию в объектной модели в зависимости от вашей текущей позиции в ней. Например, если вы выбрали набор элементов Order, вам может потребоваться произвести навигацию по атрибутам этого элемента, чтобы извлечь их значения. Или, возможно, вы выполните запрос, чтобы получить некоторый элемент Customer, а затем захотите произвести навигацию по всем дочерним элементам, чтобы извлечь их значения, не выполняя отдельных запросов для каждого элемента. Класс XPathNavigator экспонирует набор методов MoveToxxx, которые позволяют перемещаться в объектной модели, которую он экспонирует, где ххх описывает узел, на который перемещается указатель. Каждый из методов MoveToxxx возвращает булево значение, показывающее, было ли перемещение успешным, в том смысле, что в предполагаемой позиции был узел, на который можно перейти. Заметьте, что атрибуты и пространства имен рассматриваются как специальные виды узлов, поскольку они могут содержаться только в открывающем теге уз — ла-элемента. Для навигации в атрибутах или пространствах имен используется отдельный набор методов MoveToxxx, показанный в таблице

Инициализация и обновление привязок данных

хотя на словах это представляется

Реализация методов Beginlnit И Endlnit Интерфейса ISupportlnitialize Предотвращает выполнение привязки данных во время инициализации, для чего устанавливается флаг , Проверяемый методом UpdateDataBinding, И привязка данных откладывается, пока инициализация не будет завершена явным вызовом UpdateDataBinding Из метода Endlnit. Для реализации метода UpdateDataBinding Вам нужно войти в источник данных, найти коллекцию данных, специфицируемую компонентом данных, и произвести итерацию по элементам данных, чтобы отобразить столбчатые диаграммы. Хотя на словах это представляется не особенно сложным, реализация может оказаться весьма запутанной, если принять во внимание, что источник данных мог бы быть набором данных, таблицей данных, массивом, специальной коллекцией, списком списков списков и т. д. Охват всех этих сценариев может стать очень сложным. По существу здесь нужно взять источник данных и попытаться привести его к типу одного из различных интерфейсов, описанных в главе 7. Как только вы выясните, к какому типу относится коллекция, вы сможете использовать реализацию интерфейса и DataMember Для определения действительного списка данных, к которому вам нужно привязаться. К счастью, реализация большей части этой неприятной работы экспонируется через метод класса ListBindingHelper С именем GetList.

Сначала метод проверяет, не производится ли инициализация элемента управления; в этом случае он ничего не делает. Если элемент управления не инициализируется, метод убеждается, что у него есть по крайней мере источник данных и идентификатор строки, с которыми можно работать. Затем он вызывает метод GetList Класса ListBindingHelper. Этот метод делает за вас массу непростой работы, связанной с различными интерфейсами, обсуждавшимися в главе 7. В принципе его действия сводятся к следующему. Сначала он проверяет источник данных на предмет реализации интерфейса IListSource. Если интерфейс реализован, он использует метод GetList этого интерфейса для получения списка. Затем метод проверяет компонент данных и пытается разрешить его на источнике данных, чтобы возвратить в качестве списка. Метод проходит по кругу еще несколько раз, обрабатывая различные комбинации вроде списка списков, есть компонент данных или его нет и т. д., но по существу он занимается поиском действительной коллекции IList По переданному источнику и компоненту данных. Если пригодную для работы коллекцию найти не удается, вспомогательный метод привязки данных прекращает попытки и возвращает Null.

Внутренние механизмы Win Fx

рисуете ли вы на экране

Внутренние механизмы WinFx осуществляют все рисование на экране через графическую машину DirectX, что значительно повышает производительность многих графических операций и позволяет программировать сложные приложения мультимедиа, используя единственный, комплексный, объектно-ориентированный API вместо двух, когда приходится выбирать между более простым GDI+ и низкоуровневым DirectX. Рисуете ли вы на экране специальные элементы управления, внедряете в документ анимацию и видео или пишете сложный симулятор или игру, программирование в WinFx будет единообразным и сравнительно несложным. Приложения WinFx могут запускаться и как автономные приложения рабочего стола, и как встроенные элементы управления или страницы в Web-браузере.

Помимо отличий в программировании машины отображения, в WinFx имеются существенные отличия, касающиеся общего способа программирования приложений. В WinFx используется модель композиции элементов управления, которая позволяет вам создавать визуально насыщенные и единообразные по стилю пользовательские интерфейсы как в Windows, так и в Web-приложениях, написав гораздо меньше кода, чем требуют существующие технологии представления. Вы можете применять стили к контейнеру, содержащему элементы управления, избегая тем самым многократной установки одних и тех же стилевых аспектов. Вы можете также создать контекст привязки данных, который будет автоматически воздействовать на дочерние элементы, благодаря чему достигается композиционный подход к привязанным элементам управления. Последующие разделы дадут вам об этом более ясное представление.

Выполнение обновлений в базе данных

г изображен простой пример того

Фундаментальной проблемой, которой почти всегда приходится уделять внимание при выполнении обновлений в базе данных, является вопрос, как обрабатывать параллельные обновления одних и тех же данных. На рис. Г.4 изображен простой пример того, каким образом конкурентные обновления могут приводить к неприятностям. На рис. Г.4 клиент 1 извлекает из таблицы строку. Затем появляется клиент 2 и извлекает ту же самую строку. Клиент 2 обрабатывает строку несколько быстрее и фиксирует ее обновления в базе данных раньше клиента 1. Вопрос, который приходится решать при конкуренции, следующий: что должно происходить, когда клиент 1, в свою очередь, попытается записать свои изменения той же самой строки? Можно было бы допустить стратегию «последнего слова» и всегда записывать значения обновления в строку, не рассматривая ее текущего содержания. По существу это отсутствие контроля конкуренции. Если бы вы поступили так в сценарии на рис. Г.4, изменения, сделанные клиентом 2, были потеряны. Если вы работаете с моделью подключенных данных, то существует ряд способов разрешения такой ситуации при помощи замков на таблицах или строках на стороне сервера, которые предотвращают параллельный доступ или обновления в зависимости от уровня изоляции, который вы хотите обеспечить. Это очень сложная сама по себе тема, не имеющая на самом деле отношения к модели отключенных данных, используемой в ADO. NET. Чтобы справиться с конкурентным нарушением, вы прежде всего должны обнаружить, что оно произошло. В ADO. NET это делается путем сравнения текущего содержимого столбцов в базе данных с тем, что было первоначально из нее извлечено. Если текущее содержимое строки в базе данных отлично от того, что кэшировал код клиента ADO. NET, то предпосылка оптимистической конкуренции нарушена и с этим надо что-то делать. Как уже говорилось, набор данных сохраняет исходные значения для любой строки, подвергающейся модификации. Это делает очень простым сравнение значений и принятие решений в отношении оптимистической конкуренции, как только конфликт обнаружен.

Автоматическая установка размера столбцов сетки

так как программисты использующие ваш

Прежде чем объявить этот элемент управления законченным, я хочу снабдить его еще одной функцией. Так как программисты, использующие ваш элемент FilteredGrid, Не будут иметь непосредственного доступа к содержащейся в нем сетке, у них нет возможности декларативно устанавливать имена столбцов, их ширину и т. п. в конструкторе, который просто автоматически генерирует столбцы в зависимости от данных. В дополнение к этому весьма желательно, чтобы ширина столбцов также устанавливалась автоматически, так что их содержимое отображалось бы без переносов. Как говорилось в главе 6, в классе DataGridviewColumn Имеется свойство AutoSizeMode, Установив которое равным Allcells , можно достичь желаемого эффекта. Поэтому нужно добавить в FilteredGrid Немного кода, чтобы установить это свойство для автоматически генерированных столбцов данных. Возможно, вы также захотите дать программистам возможность выключать при желании эту функцию. Чтобы устанавливать это свойство столбцов, последние, естественно, должны существовать, что невозможно, пока не будет завершена привязка данных. К счастью, когда это происходит, элемент управления DataGridview Возбуждает событие DataBindingComplete, Что предоставляет вам самое подходящее место для выполнения подобных операций. Добавьте обработчик события для DataBindingComplete, Выбрав сетку в пространстве конструирования элемента управления FilteredGrid, И назовите обработчик OnGridDataBindingComplete. Добавьте свойство и соответствующий закрытый элемент класса, чтобы пользователи вашего элемента управления могли задавать, должна ли ширина столбцов устанавливаться Код обработчика события DataBindingComplete Проходит в цикле по всем столбцам сетки, устанавливая для их свойства AutoSizeMode Соответствующее перечислимое значение. Проделав все вышеописанное, вы получаете весьма законченный работоспособный образец специального элемента управления с привязкой к данным, созданный как пользовательский элемент управления, содержащий другие привязанные элементы управления, и управляемый через инкапсулированный источник привязки. Такой подход дает вам естественный способ инкапсуляции функций в одиночном элементе управления, который может быть утилизирован в разных местах, и позволяет в полной мере воспользоваться мощью встроенных элементов управления Framework, не зная о них ничего, кроме их открытых свойств, методов и событий.