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

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

net framework предусмотрен богатый набор

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

Вы можете склониться в пользу реализации своих собственных привязанных элементов управления по целому ряду причин, в числе которых можно назвать следующие: Вам нужны сходные функции специального назначения в различных частях вашего приложения или в нескольких различных приложениях. Вы захотите инкапсулировать сложности кода специального назначения, даже если и не видите потенциальной возможности его утилизировать. Инкапсуляция хороша как с точки зрения потенциальной утилизации, так и с точки зрения изоляции различных частей вашего кода, чтобы с этим кодом должны были иметь дело только те, кому нужно знать его детали и работать с ними. Вы захотите создать специальный элемент управления, инкапсулирующий код, который должен навязывать нужное вам поведение элементам управления Framework. Вы можете однажды закодировать специализированные функции в виде специального элемента управления, чтобы потом многократно утилизировать его точно так же, как вы используете элементы управления из Framework. Вам нужны функциональные возможности или способы представления данных, не обеспечиваемые в настоящий момент элементами управления Framework. Код, который потребуется написать для реализации специального элемента управления, привязанного к данным, зависит от того, насколько он специализирован. В этой главе показано несколько примеров специальных элементов управления, которые демонстрируют различные подходы к специальным элементам и обсуждаются соображения за и против каждого подхода. Здесь описывается, как получить субкласс существующего элемента управления из Framework, как инкапсулировать существующие эле

Модификация поведения при рисовании ячейки

далее нам нужно обрабатывать рисование

Таким образом, мы позаботились об отображении для ячейки пустого содержимого, если ее значение то же, что и в предыдущей строке. Далее нам нужно обрабатывать рисование границ ячеек так, чтобы пустые ячейки для повторяющихся значений отображались в сетке как одна большая ячейка. Для этого нужно переопределить метод OnCellPainting Базового класса, как показано в листинге 8.2. Вот и все. Если вы скопируете этот код или запустите образец программы CustomControlsHost из загружаемого кода, то увидите специальную сетку в действии. Этот пример довольно несложен, но весьма далек от настоящей реализации. Он не обрабатывает корректно случаи, когда пользователь настраивает границы ячеек по умолчанию, и в базовом классе имеются еще свойства, установка которых может привести к нежелательным эффектам при запуске кода. В этом опасность создания класса непосредственно как производного от элемента управления Framework: любые модификации, вносимые в его поведение посредством доступа к защищенным элементам, предполагают, что вы в точности знаете, как сделанные изменения повлияют на поведение базового класса. В случае сложного элемента управления вроде DataGridView Вам придется слишком глубоко погружаться в его внутреннее устройство. Лучшим подходом будет инкапсуляция элемента управления и настройка его поведения через открытый API, что мы вскоре рассмотрим. Назовите элемент управления FilteredGrid. Тем самым к вашему проекту будет добавлен новый файл пользовательского элемента управления и отображено рабочее пространство конструктора для него, похожее на пространство конструктора формы. Увеличьте размер элемента управления, захватив его границу и растянув его вниз и вправо до размера примерно 600 на 350 пиксел. Взяв рис. 8.5 за образец, добавьте к пользовательскому элементу две метки, текстовое поле, две кнопки, комбинированное поле, источник привязки И элемент управления DataGridview, Перетащив их из окна Toolbox. Расположите их, как на рис. 8.5. Источник привязки будет показан в панели невизуальных компонентов в нижней части конструктора. Установите свойство Text Меток и кнопок в соответствии с рис. 8.5, а свойство Text Текстового поля оставьте пустым. Дайте имена текстовому полю, комбинированному полю, кнопке, источнику привязки и сетке, соответственно M_FilterTextBox, M_Fields — Combo, M_FilterButton, M_ClearButton, 6. Включите в свойство Anchor Сетки значения Top, Bottom, Left И Right, Чтобы она автоматически изменяла свой размер, заполняя нижнюю часть пользовательского элемента управления при любом его размере.

Метод обработчика OnLoadData

в этом примере вы можете

Метод обработчика OnLoadData Имеет сигнатуру, определяемую делегатом EventHandler, Который используется многими событиями элементов управления Windows Forms. В этом примере вы можете игнорировать передаваемые методу аргументы, но метод все равно должен объявлять эти аргументы, чтобы соответствовать определению типа делегата события.

Для обработчика события вы можете использовать любое имя, какое захотите, но я предлагаю вам следовать единообразному и легко читаемому соглашению об именах для ваших обработчиков событий. Я обычно даю им имена вида Оп<действие>, Как в этом примере. Вы часто будете создавать эти обработчики при помощи конструктора, а он, как вы увидите в следующем разделе, применяет несколько иное соглашение об именах, поэтому я, чтобы получить нужные мне имена методов, обычно устанавливаю имена своих обработчиков событий при помощи окна Properties. Код в обработчике события создает объект набора данных и загружает в него некоторые данные, используя метод Readxml, Как показано в приложении Г. Исходный файл XML может быть любым допустимым кодом XML, подходящим для загрузки в набор данных, в котором имеется хотя бы одна таблица данных. В настоящем случае используется та же самая упрощенная версия XML для набора данных Customers, что показана в разделе «Загрузка наборов данных из файла» приложения Г. Как только набор данных заполнен, вы привязываете к сетке первую таблицу в наборе данных, используя свойство DataSource Сетки. В основных главах этой книги механика процесса привязки данных рассмотрена более подробно, но для целей настоящего приложения достаточно сказать, что когда вы устанавливаете свойство DataSource Сетки на таблицу данных, сетка извлекает информацию о схеме и создает столбец для каждого столбца в таблице, после чего перебирает строки в таблице, добавляя для каждой соответствующую строку, содержащую данные.

Интерфейс ISupportlnitialize: поддержка инициализации в конструкторе

тем самым предотвращается попытка элемента

Интерфейс ISupportlnitialize Позволяет элементам управления отложить действия со значениями, устанавливаемыми во взаимозсвязанных свойствах, пока контейнер не сообщит элементу управления, что все значения установлены. Тем самым предотвращается попытка элемента управления что-то сделать с установленным свойством, когда эти действия могут потерпеть неудачу из-за того, что сначала нужно установить какое-то другое свойство; таким образом, эти свойства можно устанавливать в любом порядке. Конструктор Windows Forms Использует этот интерфейс, так что коду, который он генерирует для установки свойств, не требуется что-либо знать о правильном порядке установки взаимосвязанных свойств. Иногда компоненты имеют взаимосвязанные свойства, которые, чтобы все работало правильно, требуется устанавливать логически одновременно. Но поскольку за один раз можно исполнить только одну строчку кода, требование одновременной установки нескольких свойств оказывается проблематичным. Например, если вы специфицируете свойство DataMem — Ber Для компонента BindingSource Или элемента управления DataGrid — View, Это свойство предоставляет информацию о том, какая составная часть объекта, устанавливаемого в качестве свойства DataSource, Должна использоваться для привязки данных. Любое изменение свойства DataMember Делает необходимым обновление привязок данных. Однако свойство DataMember Не поймет, что от него требуется, если только ранее уже не было установлено свойство DataSource. Вы не можете быть уверены, что свойства будут устанавливаться в правильном порядке, сначала DataSource, А затем DataMember. Кроме того, что получится, если вы захотите взять компонент или элемент управления, который был уже привязан к какому-то источнику данных, и заменить последний новым источником данных? Вы могли бы изменить сначала свойство DataSource, А могли бы сначала изменить свойство DataMember. Когда конструктор пишет код, руководствуясь вашими интерактивными действиями вроде выбора в контекстной вкладке или установки свойств в окне Properties, Нельзя сказать наверняка, в каком порядке будут инициализироваться эти свойства в написанном коде. Поэтому должен быть способ сигнализировать элементу управления или компоненту, что вы приступаете к этапу инициализации, а затем, когда вы закончите с этим этапом, снова уведомить его. Если можно это сделать, то компонент может подождать с установкой взаимосвязей или использованием значений любых свойств, пока вы не сигнализируете ему, что инициализация завершена. Именно для этого предназначен интерфейс ISupportlnitialize.

Работа с классом XPathDocument

это по существу новая объектная

Как подразумевает имя класса, XPathDocument Является объектной моделью, которая основана на иерархической модели, определяемой спецификацией XPath. Это по существу новая объектная модель для хранения XML-содержания, введенная в. NET 1.0 как хранилище только для чтения, которое имеет меньший вес и лучшую производительность, чем реализация DOM в XmlDocument. Этот класс и родственные ему классы находятся в пространстве имен System.Xml .XPath. Обычно вы не работаете с XPathDocument Непосредственно, за исключением нескольких общих операций. Первое, что вам нужно сделать — это загрузить в документ данные. Данные могут поступать из различных источников, включая файл на диске, сетевой поток, вызов Web-службы или запрос к базе данных. Как только вы загрузили данные в документ, следующим шагом будет получение для него XPathNavigator, Который является основным API для доступа к данным внутри документа XML. Вы можете также получить объекты XPathNavigator Для XmlDocument И XmlDataDocument, Чтобы можно было пользоваться единообразной моделью программирования XML для всех трех типов документов. Кроме того, через XPathNavigator Вы можете непосредственно редактировать данные в объектах XmlDocument И XmlDataDocument. Помимо этих операций, большинство из того, что вас будет интересовать при работе с XPathDocument, Связано с программированием объекта XPathNavigator, Который вы можете использовать для выполнения запросов к документу и для навигации по набору узлов. Есть два общих способа загрузки данных в XPathDocument. Первый — из файла, для чего нужно просто передать путь к файлу или URL конструктору класса

Конструктор может также принимать поток, XmlReader Или TextReader. Какой бы источник вы ни использовали, содержимое документа будет загружено в память, синтаксически проанализировано и помещено в нижележащую модель XPathDocument. Чтобы получить данные из SQL Server, вы можете выдать запрос FOR XML и загрузить XPathDocument При помощи XmlReader, Возвращаемого вызовом ExecuteXmlReader Объекта