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

Поиск в наборах данных

не забывайте что b dataset

Когда вы заполните набор данных, вам часто бывает нужна возможность поиска и выбора данных внутри него, либо для выполнения обновлений или обработки на каком-то подмножестве данных, либо для целей отображения. Не забывайте, что DataSet И родственные ему классы не предназначены для использования в качестве высокоэффективной машины запросов. Хотя вы можете выбирать и фильтровать данные в таблице данных на стороне клиента, во многих случаях может оказаться быстрее просто исполнить новый, более специализированный запрос к базе данных, чтобы получить специфические результаты, которые вы ищете. Это особенно верно при работе с локальным экземпляром базы данных, таким, как база данных SQL Express. Однако если данные уже находятся в памяти в DataSet, И вы хотите выбрать некоторые элементы, не путешествуя к базе данных и обратно, можно применить несколько подходов. Простейшим является использование метода Select Класса DataTable, Позволяющий исполнять SQL-подобные запросы к данным, содержащимся в таблице. Вы можете также использовать псевдотаблицы, чтобы фильтровать данные в соответствии с критериями отбора, либо использовать класс XmlDataDocument, Чтобы загрузить данные в контейнер XML-документа и исполнять на них запросы XPath. У метода Select Есть несколько перегрузок, которые позволяют вам искать по строковому критерию, напоминающему предложение WHERE в SQL, и опционально передавать порядок сортировки или перечисление DataRowviewState, Чтобы искать среди записей в определенном состоянии или состояниях. Метод Select Возвращает массив объектов DataRow, Содержащих ссылки на строки, удовлетворяющие критерию отбора. Как только вы получите этот массив строк, вы можете итерировать их и производить над ними любую необходимую обработку. Вы работаете с живыми ссылками на действительные строки в наборе данных, поэтому любые сделанные в них изменения немедленно повлияют на данные в наборе данных. Следующий код показывает операцию Select На наборе данных Customers с использованием двух перегрузок метода.

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

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.