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

Определение специального типа ячейки

если вы собираетесь рисовать самостоятельно

Первым шагом реализации приложения будет определение специального типа ячейки. Если вы собираетесь рисовать самостоятельно, можно переопределить защищенный виртуальный метод Paint Базового класса DataGridViewCell. Однако если содержимое ячейки, которое вы хотите отображать, является лишь вариацией одного из встроенных типов ячеек, то следует рассмотреть возможность наследования от одного из этих типов. Именно это я и сделал в данном случае. Поскольку мои специальные ячейки должны показывать изображения, естественным базовым классом для них будет DataGridViewlmageCell. Однако мой класс StatusCell Не будет предусматривать возможность установки произвольных изображений; он предназначен для работы с перечислимыми значениями. Я хочу также, чтобы ячейка могла оперировать целыми значениями, если они укладываются в диапазон соответствующих численных значений перечисления, чтобы можно было поддерживать обычную ситуацию, когда перечислимые типы сохраняются в базе данных как целые значения. Код листинга 6.4 показывает реализацию класса StatusCell. В этом коде сначала объявляется перечисление Statuslmage. Оно будет ожидаемым типом для свойства Value Данного типа ячейки. Далее вы видите, что тип StatusCell Является производным от DataGridViewImage — Cell, Поэтому я могу воспользоваться способностью последнего представлять изображения внутри сетки. Имеется поле состояния по умолчанию и соответствующее свойство, позволяющее непосредственно прочитать значение состояния по умолчанию. Конструктор, кроме того, устанавливает для свойства ImageLayout Базового класса значение Fill, Поэтому изображения масштабируются так, чтобы они вписывались в ячейку без искажения.

Ключевым моментом в специальном типе ячейки является либо переопределение метода Paint, О чем уже упоминалось, либо переопределение метода GetFormattedValue, Что и делается в классе StatusCell. Этот метод будет вызываться всякий раз при отображении ячейки, и позволяет вам обрабатывать преобразование значений других типов в тип, ожидаемый ячейкой. Я решил, что код метода GetFormattedValue В этом примере должен сначала установить для ячейки некоторое значение по умолчанию, на случай, если ничего другого сделано не будет. Затем код пытается получить действительное значение по умолчанию из свойства Defaultvalue Содержащего ячейку столбца, если это столбец типа StatusColumn . Код проверяет, что текущее свойство Value Является перечислимым типом Statuslmage Или целым, и если оно целое, приводит значение к перечислимому типу.

Свойство DataSource

b если сам источник данных

Свойство DataSource Может устанавливаться на любую коллекцию объектов, которая поддерживает один из четырех интерфейсов: IList, IList — Source, IBindingList Или IBindingListView. Если сам источник данных является коллекцией коллекций данных, такой, как набор данных, или источник реализует интерфейс IListSource, То свойство DataMemder Должно идентифицировать в источнике данных ту коллекцию, к которой производится привязка. Если свойство Datasource Установлено на объект, реализующий IList , ТО Свойство DataMemder Может быть равно Null . Когда вы привязываете DataGridView К источнику привязки, то поскольку сам класс BindingSource Реализует интерфейс IBindingListView , вы можете в действительности привязать сетку к любой коллекции, с которой может работать источник привязки, в том числе к простым коллекциям, реализующим только IEnumerable. Всякий раз, когда устанавливается свойство Datasource И/или свойство DataMemder, Сетка будет перебирать находящиеся в коллекции данных элементы и обновлять привязанные к данным столбцы таблицы. Если сетка привязана к источнику привязки, любые изменения в скрытом за ним привязанном источнике данных будут также приводить к обновлению привязанных столбцов сетки. Это происходит благодаря событиям, возбуждаемым источником привязки в привязанных элементах управления при любых изменениях в лежащей под ним коллекции.

Всякий раз при установке свойств Datasource И DataMemder Они запускают соответственно события DataSourceChanged И DataMemberChanged. Это позволяет вам подключить код, исполняемый в ответ на изменение привязки данных в сетке. Вы можете также реагировать на событие DataBin — DingComplete, Поскольку оно запускается после того, как изменяется источник или элемент данных и обновляется привязка данных.

Ваше первое приложение Windows Forms для данных

я объясню шаги создания приложения

Первое приложение поведет вас на один шаг дальше обычного «Hello world»; вы создадите очень простое приложение, которое загружает некоторые данные и отображает их в сетке. Я объясню шаги создания приложения с чисто программной точки зрения, а в следующем разделе вы повторите его создание, используя Windows Forms. Таким образом вы получите представление как о том, что происходит за кулисами, так и о том, как это делается быстро и просто при помощи конструктора Visual Studio. Затем мы углубимся в то, что происходит за кулисами, чтобы вы поняли, откуда берутся все функциональные возможности Windows Forms. Итак, давайте начнем с чисто программного подхода.

Метод Main Является входной точкой любого приложения. NET. В Visual Studio 2003 он всегда помещался в первый класс Form, Добавляемый к проекту. В Visual Studio 2005 к проекту добавляется класс Program В качестве отдельного файла кода, чтобы метод Main Не потерялся при удалении из проекта первой формы. Мы следуем здесь тому же подходу, но для простоты просто разместили этот класс в том же файле. Атрибут необходим, если приложение будет использовать какие-либо элементы управления ActiveX, буфер обмена или какие-либо COM-объекты в однопоточном разделе, поэтому в Visual Studio он по умолчанию добавляется к любым проектам приложения Windows, и, как правило, он всегда вам потребуется. Чтобы сделать доступным этот тип атрибута, вы должны подключить оператором Using Пространство имен System. Чтобы компилировать этот файл при помощи компилятора C# с командной строкой, откройте окно командной строки Visual Studio в группе Microsoft Visual Studio, подменю Visual Studio Tools), перейдите в папку, где находится файл, и введите команду:

NET Framework имеется ряд встроенных типов объектных коллекций

net framework имеется ряд встроенных

В. NET Framework имеется ряд встроенных типов объектных коллекций, и вы сами можете создавать свои собственные типы коллекций, если вам нужно, чтобы коллекция поддерживала возможности, не предусматриваемые доступными типами коллекций. До. NET 2.0 потребность в создании специальных коллекций возникала достаточно часто, если вам хотелось иметь безопасные по типам коллекции данных или рабочих объектов. С введением обобщений в. NET 2.0 необходимость реализации специальных классов коллекций будет весьма редкой. Классы List<T>, Dictiona — Ry<T>, Queue<T>, Stack<T>, LinkedList<T> И SortedDictionary<T> Должны быть достаточны для большинства ситуаций, когда вы захотите реализовать специальную сильно типизированную коллекцию объектов. Кроме того, в Widows Forms имеется класс BindingList<T> Для привязки данных, реализующий большинство интерфейсов, которые вам потребуются. Подробно BindingList<T> Рассматривается в главе 9, но вы уже видели его в действии во многих примерах из предыдущих глав. Учитывая все вышесказанное, существует потенциально неограниченное число типов коллекций и объектов, доступных для привязки данных в ваших приложениях. Так каким же образом вы можете охватить все это разнообразие? Это делается путем определения общего контракта, поддерживаемого всеми типами, которые должны совместно участвовать в привязке данных. Наилучшим средством спецификации контракта для кода, не замкнутого на реализацию этого контакта, является интерфейс. Определения интерфейсов должны рассматриваться с двух точек зрения: с точки зрения реализатора и с точки зрения потребителя. Реализатором является класс, в котором предусмотрена реализация элементов, определенных в интерфейсе. Потребителем является код, который получает ссылку на интерфейс объекта и активирует через нее функции, предоставляемые этим интерфейсом.

Обзор программирования пользовательских интерфейсов и возможностей WinFx

это касается подхода к целевым

WinFx вводит ряд новых концепций и подходов к программированию приложений с интерфейсом пользователя для Windows. Это касается подхода к целевым дисплейным устройствам и отображению графики, программирования элементов UI и нового декларативного языка для спецификации UI-приложений. Прежде всего WinFx пытается уйти от ориентированной на пикселы программной модели низкоуровневой графики, отображаемой на рабочем столе пользователя. Существующие дисплеи способны передавать изображения с невероятным разрешением. Если при отображении на дисплее элементов UI исходить из их размеров в пикселах, как это обычно и делается сегодня в приложениях Windows, то при запуске приложений вы получите для различных устройств и дисплеев огромный разброс в размерах элементов UI. Хотя сегодня в GDI и GDI+ существуют способы преобразования размеров в логические единицы, первичная программная модель ориентирована на пикселы. В WinFx модель обратная; первичные вызовы API для графических операций ориентированы на логические единицы. Кроме того, сегодняшний подход к отображению графики в Windows основан на растровых операциях — отображении элементов на дисплее как матриц из пикселов. Но большинство рисуемых объектов представляют собой геометрические фигуры, такие, как прямоугольники и кривые, которые проще отображать посредством векторной графики. WinFx делает векторную графику, как таковую, первичной низкоуровневой методикой рисования. При этом становится значительно проще выводить, например, на экран элементы UI и затем выполнять над ними преобразования — вращать, масштабировать или перемещать. Это делает программирование анимационных эффектов гораздо более простым и естественным.