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

Преобразования типов и обработчики формата

классы typeconverter b b определяются

Для каждого встроенного типа.NET Определены функции преобразования, либо через класс, производный от TypeConverter, Либо через неявные преобразования данных в механизме привязки Windows Forms. Классы TypeConverter Определяются и ассоциируются с определенными типами, при этом они предназначены для преобразования из ассоциированного типа в один или несколько других типов. Например, класс ImageConverter Ассоциирован с типом Image, И он может выполнять преобразование в битовый массив и наоборот. Если для требуемого преобразования не существует TypeConverter, Используются возможности неявного преобразования типов Windows Forms, которые поддерживают наиболее употребительные типы.NET. Кроме того, процесс преобразования типов может корректировать значения, полученные от Обработчика формата , т. е. объекта, реализующего интерфейс IFormatProvider. Например, класс DateTimeCon — Verter Ассоциируется с типом DateTime, И может выполнять преобразования значений даты-времени из строки или в строку. Результат процесса преобразования типа String Может быть модифицирован обработчиком формата. Обработчиком формата для типа DateTime Является по умолчанию DateTimeFormatinf О, И вы можете легко задать ему, какие именно части значения даты-времени необходимо извлечь и вернуть в результирующей строке.

Содержание преобразованной строки задается путем спецификации строки формата, состоящей из маркеров, идентифицирующих части значений даты и времени. Имеются предопределенные строки формата, доступные для локализации, такие, как "D", Которая означает, что возвращаемая строка должна содержать дату в коротком формате. Обработчик формата также поддерживает специализированные строки формата, которые можно использовать для передачи маркеров обработчику формата. Дату в таком же формате можно вернуть при помощи строки формата "Mm/Dd/Yyyy", Но такие строки не будут автоматически адаптированы к локальным стандартам, как это происходит с предопределенными строками формата.

Методы GetXXX

методы принимают индекс столбца или

Методы GetXXX, Извлекающие значение столбца, определены для каждого из встроенных типов. NET. Методы принимают индекс столбца, или ординал, для позиции извлекаемого столбца, и пытаются извлечь значение столбца как указанный тип, производя при необходимости любые преобразования. Например, если вы вызываете метод GetString Для столбца, который в действительности содержит целое, для возвращаемого значения будет вызван ToString, Чтобы получить строку. Если вы попытаетесь использовать метод Getxxx, запрашивающий тип, несовместимый с действительным содержанием столбца, будет выброшено исключение. Чтобы определить позицию столбца, этот код использует метод считывателя данных GetOrdinal, Отыскивающий позицию столбца по его имени. Считыватель данных экспонирует интерфейс, аналогичный другим классам считывателей в. NET Framework. Считыватель действует подобно указателю в коллекцию элементов. Указатель исходно позиционирован непосредственно перед первым элементом. Чтобы переместить указатель на следующий элемент, вы вызываете метод Read Считывателя. Если элементов для чтения больше нет, метод Read Возвратит False. Когда указатель позиционирован на элементе, вы можете обращаться к содержимому этого элемента через те методы доступа и свойства, которые экспонирует специфический тип считывателя. В случае SqlDataReader Элементами являются строки, а к содержимому строк вы можете обращаться через индексатор, свойство Item Или методы GetXXX, Где XXX Обозначает тип столбца, который вы запрашиваете. Следующий код показывает использование индексаторов и метода Индексатор считывателя данных возвращает ссылку на object, поэтому вам нужно будет приводить значение к ожидаемому типу столбца, который вы извлекаете. Индексатор перегружен таким образом, что вы можете передавать ему либо целый индекс в строке, представляющий позицию столбца в возвращаемых строках, либо имя столбца, как показано здесь. Использование имен столбцов гораздо проще для чтения и сопровождения, хотя и чуть-чуть менее эффективно при извлечении.

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

следующий блок кода в листинге

Элемент управления Grid Является контейнером и позволяет вам легко располагать элементы управления в прямоугольной сетке на отображаемой поверхности какого-то другого элемента, установив сетку в качестве его содержимого. Следующий блок кода в листинге Б.1 создает для сетки определения столбцов и строк, после чего устанавливает их свойства width и Height, Чтобы получить желаемую планировку сетки.

Следующий блок кода вызывает вспомогательный метод, показанный в конце листинга, чтобы поместить каждый из элементов управления в нужную позицию сетки. К сожалению, при существующей в WinFx программной модели для каждого из элементов управления требуется три строки кода, чтобы просто поместить элемент в ячейку сетки: Вспомогательный метод AddControlToGrid Инкапсулирует эти три вызова, что делает вызывающий код чуть компактнее. Но по существу метод устанавливает для каждого элемента управления столбец и строку, после чего добавляет его к сетке. Обратите внимание, что позиция элемента управления в сетке устанавливается при помощи статических методов самого класса Grid, А не методов или свойств экземпляра сетки. После размещения каждого элемента управления в соответствующей ячейке сетки последняя устанавливается в качестве элемента содержания окна, и для окна вызывается метод Show. Конечным результатом является окно, вид которого показан на рис. Б.1. Этот пример дает несколько более ясное представление о том, каким образом одни элементы помещаются на уровень содержания других элементов, образуя визуальное дерево элементов управления. В данный момент такой программный подход может показаться вам довольно громоздким: что же, все это только для того, чтобы спланировать простейшую входную форму? Следует помнить, что в Windows Forms потребуется для этого не намного меньше кода, но почти никто не пишет код Windows Forms вручную на пустом месте; написание большей части этого кода возлагается на конструктор Visual Studio. Однако так будет и с WinFx, когда появится ее окончательный выпуск. В настоящий момент для работы с WinFx нет конструктора, но понимание кода поможет вам, когда этот код будет генерироваться конструктором и вы вдруг обнаружите, что ваше приложение работает не совсем так, как вы хотели.

Кодирование специального элемента управления

b сопряженность отображения в элементе

Так как элемент управления должен поддерживать привязку данных по той же схеме, что и другие привязанные элементы управления, ему понадобятся свойства DataSource И DataMember. Сопряженность отображения в элементе управления с данными отдельных элементов в привязанной коллекции требует, чтобы элемент управления имел также свойство, позволяющее задать, каково имя того поля или свойства, которое содержит идентификатор строки. По смыслу это напоминает функцию СВОЙСТВ DisplayMember И ValueMember Элемента управления ComboBox Или ListBox, И я назову это свойство Rowldentif IerMember.Основной скелет определения класса показан в листинге 8.8. Класс DataBoundBarChartControl Является производным от UserControl И реализует интерфейс ISupportlnitialize, Что позволяет ему контролировать свою привязку к данным в фазе инициализации. К классу применен атрибут ToolboxBitmap, Который устанавливает значок для элемента управления, используемый при добавлении его в Toolbox. Специфицированное имя файла относится к битовой матрице 16><16, которая добавляется в проект и помечается как встроенный ресурс. Свойства DataSource И DataMember Объявляются таким же образом, как и в классе FilteredGrid, Только в настоящем случае вы не инкапсулируете источник привязки, которому можно было бы их делегировать. Вместо этого элемент управления сохраняет свойства Datasource И DataMember В элементах-переменных класса, которые он сможет использовать для привязки данных, когда это понадобится. Set-блоки этих свойств вызывают также метод UpdateDataBinding, В котором и находится действительный код привязки данных. Экспонируется также свойство RowidentifierMember, Указывающее, какое свойство элементов данных должно использоваться для отображения меток рядом с каждым экземпляром столбчатой диаграммы.

Загрузка DataTable при помощи DataReader

если то с чем вы

Позднее я собираюсь показать, как использовать считыватель данных для загрузки специальной объектной модели, но пока мы занимаемся загрузкой наборов данных, я подумал, что стоит выделить одну новую возможность в. NET 2.0. Если то, с чем вы работаете в каждый момент времени — это единственная таблица, то создание целого набора данных с индексами таблиц для того только, чтобы добраться до ваших данных, может означать массу излишних дополнительных расходов. В. NET 2.0 вы можете создать, заполнить и использовать самостоятельную таблицу DataTable, Без необходимости иметь дело со сложностями набора данных. Вы можете также, используя считыватель данных, быстрым и эффективным образом заполнить ее, не проходя для этого через адаптер данных или адаптер таблицы. Следующий код показывает вышесказанное в действии. В этом единственном блоке кода представлено несколько новых моментов, поэтому давайте разберем их по порядку. Первое, что делает этот код — создает пустую таблицу данных и называет ее Customers. Всякий раз, когда вам требуется исполнить запрос, вам нужен объект соединения, и оно создается здесь оператором Using. Если вы исполняете запрос сами, вам нужно будет сначала явным образом открыть соединение. Всякий раз, когда вы открываете соединение, вы должны обеспечить его закрытие, и вы должны это сделать даже в том случае, если в коде, предшествующем вызову Close, Будет выброшено исключение. Одним из способов сделать это является размещение кода, открывающего соединение, в блоке Try, С вызовом Close В блоке Finally. Другим способом является использование оператора C# Using, Как сделано в этом коде.

Здесь объект соединения создается в блоке Using, Что приводит к вызову для соединения метода Dispose При выходе из области действия этого блока. Метод Dispose Объекта соединения вызывает Close, А оператор Using Всегда создает за вас блок Try-Finally С вызовом Dispose В блоке Finally. Таким образом, блок Using Предлагает вам простой, легко читаемый и безопасный способ использования объектов соединения, гарантирующий, что они будут закрыты при выходе из области действия.