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

Определение специальных типов ячеек и столбцов

однако всегда встречаются особые сценарии

Имея DataGridView, Вы обладаете возможностями представления сложных данных, далеко опережающими возможности DataGrid Благодаря встроенным типам столбцов, которые поддерживаются уже в готовом виде. Однако всегда встречаются особые сценарии, в которых вам понадобится поддерживать отображение столбцов специального вида. К счастью, другим важНыМ преимуществом DataGridView Является простота подключения специальных типов столбцов и ячеек. Если вы хотите настроить только процесс рисования ячейки, но не собираетесь вводить каких-либо новых свойств или средств управления на уровне столбца, у вас есть возможность воспользоваться событиями, а не создавать для этого новые типы столбцов и ячеек. Вы можете обрабатывать событие CellPainting И рисовать прямо в ячейке, при этом можно осуществить многое из того, что вам потребуется, при помощи встроенных типов ячеек и некоторого кода рисования. Но если вы хотите подключать к сетке свои собственные утилизируемые типы столбцов или ячеек с той же легкостью, как используются встроенные типы, то можете создать свои собственные производные классы столбцов и ячеек. Модель, которой вы следуете при подключении специальных типов столбцов, совпадает с той, что вы уже видели при использовании встроенных типов: вам нужно создать тип столбца и соответствующий тип ячеек, которые будут содержаться в столбце. Это делается путем наследования от базовых классов DataGridViewColumn И DataGridViewCell, Непосредственно или косвенно, через один из встроенных классов. Лучше всего объяснить это в подробностях на примере. Допустим, я хочу реализовать специальный тип столбца, позволяющий отображать состояние элементов, представляемых строками сетки. Мне хотелось бы устанавливать состояние, используя перечислимые значения, а ячейка будет графически индицировать состояние в зависимости от установленного для ячейки перечислимого значения. Для этого я определяю классы statusCo-Lumn И StatusCell .

Простое приложение с привязкой к данным

метод b main b как

Показан класс приложения для этого примера. Метод Main, Как и раньше, создает экземпляр вашего производного класса приложения и приводит его в действие. При запуске приложения вызывается замещающий метод OnStartingUp, Который позволяет вам создать главное окно и разместить в нем элементы управления. В этом примере я в качестве контейнера верхнего уровня воспользовался элементом управления StackPanel, Чтобы расположить элементы управления вертикально, один над другим. Одним из его дочерних элементов является сетка, которая содержит элементы управления TextBlock И TextField, Отображающие привязанные поля строки. Основная часть кода выполняет элементарные операции WinFx для создания и расположения элементов управления, и аналогична коду на листинге Б.1. Строки кода, относящиеся к привязке данных, выделены жирным шрифтом. Win.DataContext = Custs;Вызовы метода SetBinding Для поля списка и текстовых полей задают путь в контексте данных для этих элементов управления. В случае поля списка свойством, определяющим привязку, является ItemSource, А привязывается оно к экземпляру класса Binding, Создаваемому по умолчанию. Метод SetBinding Принимает аргумент типа DependencyProperty, Предоставляющий информацию о типе свойства в привязанном объекте, которое подлежит привязке, и путь внутри контекста данных. Этот путь будет использоваться во время выполнения для динамического разрешения привязки в соответствии с текущим контекстом данных и информацией о пути, предоставляемой экземпляром объекта Binding. Когда вы создаете экземпляр объекта Binding По умолчанию, в качестве пути устанавливается корень контекста данных. Альтернативно можно задать, как для текстовых полей, путь к подобъекту или коллекции. Для текстовых полей идентифицируется имя свойства в объектах коллекции, которое используется для заполнения свойства Text В TextBox. Данными, с которыми работает этот пример, является специальная коллекция объектов Customer, Создаваемая в обработчике события Window — Loaded И задаваемая в качестве контекста данных для окна через его свойство DataContext. Конструктор по умолчанию класса CustomersCollection Помещает в коллекцию три тестовых объекта, которые мы и видим во время выполнения. После установки контекста данных обновляются привязки всех дочерних элементов управления, и отыскиваются их пути внутри этого контекста.

Обобщенные классы коллекций. NET Framework

net вы реализовывали специальные классы

В. NET 1.1 вы реализовывали специальные классы коллекций, используя класс CollectionBase И лежащий под ним ArrayList. Тут имелись некоторые проблемы, поскольку за кулисами все сохранялось и извлекалось через сырую ссылку Object, Что порождало проблемы с эффективностью, обусловленные упаковкой и распаковкой для типов-значений и приведениями для любых типов. Одним из важнейших нововведений в. NET 2.0 на уровне Framework явились обобщения. Вы уже познакомились с применением обобщений в ряде примеров этой книги, но полное обсуждение обобщений выходит за рамки ее тематики. Тем не менее использование обобщенных классов коллекций является центральным моментом привязки данных в приложениях Windows Forms со специальными рабочими объектами, поскольку обобщенные коллекции решают все проблемы, о которых уже говорилось в этой главе. Когда вы используете обобщенные классы коллекций, вы фактически объявляете сильно типизированный класс коллекции, просто объявляя экземпляр обобщенного класса с параметризованным типом. Рассмотрим, например, следующую строчку кода: Эта строка объявляет элемент-переменную типа List<Customer> И создает экземпляр этого типа. Параметром обобщенного типа является Customer, Который указывает, что должен быть создан новый обобщенный тип List, Содержащий объекты Customer. По синтаксису и семантике обобщения аналогичны шаблонам C++, но реализация их сильно отличается и более эффективна. Это простое объявление эквивалентно по своей функции определению целого класса, подобного показанному в листинге 9.1, но гораздо эффективнее в плане памяти и исполнения. Оно дает вам класс безопасной по типу коллекции для объектов любого рода, просто объявляя новый экземпляр обобщенного типа List<T> С соответствующим параметром типа , Специфицирующим тип объектов, для хранения которых предназначается коллекция.

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

форматирование элемента управления b detailsview

DetailsView — это новый удобный элемент управления, который устанавливает таблицу, отображающую детали отдельной единицы данных для более естественного просмотра. Форматирование элемента управления DetailsView Можно представить себе так, как будто он поворачивает одиночную строку табличной сетки набок, представляя заголовки столбцов как заголовки строк, а значения полей из желаемой строки как примыкающие к ним ячейки в каждой из этих строк. Пример показан на рис. А. З. Для использования DetailsView Вы устанавливаете управляющий элемент источника данных, как описывалось выше, и помещаете его ID В свойство DataSourcelD Элемента управления DetailsView. Задать, какую следует выбрать строку в источнике данных, вы можете либо ограничив запрос к источнику, чтобы он возвращал только одну единицу данных , Либо установив свойство FilterExpression Значением, которое отфильтрует желаемую строку. Код для страницы, показанной на рис. А. З приведен в листинге А.8.Av

Обратите внимание, что здесь два элемента управления SqlDataSource. Первый установлен как источник данных сетки и получает из базы данных все записи заказчиков. Второй установлен в качестве источника данных для элемента управления DetailsView И посредством ограничения Select . . . Where Определяет, какая строка выбирается. Параметр выбора определяется динамически через ControlParameter, Указывающий на элемент управления сетки, а его свойство SelectedValue Принимает значение ключевого поля выбранной строки, которое содержит CustomeriD. Элемент управления DetailsView Поддерживает также пагинацию, редактирование и многие из других возможностей самого GridView. Он предназначен для операций над единственной строкой за раз, поэтому источник данных должен быть установлен соответствующим образом.

Интерфейс IRaiseltemChangedEvents: осуществление уведомлений об изменении элемента

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

Интерфейс IRaiseltemChangedEvents Позволяет коллекции указать, что она будет отслеживать изменения свойств содержащихся в ней объектов, производимые посредством метода SetValue Их дескрипторов свойств. Это может потребоваться, если вы ожидаете, что ваш тип коллекции может содержать объекты, которые не будут поддерживать интерфейс INotifyPropertyChanged, Но Хотите предусмотреть какую-то возможность уведомлять привязанные элементы управления о том, что свойства нижележащего элемента данных изменились. Этот интерфейс ничего не гарантирует относительно уведомления об изменениях, производимых какими-то средствами, отличными от метода SetValue Их дескрипторов свойств. Этот интерфейс используется в качестве сигнала потребляющему коду, что ваша коллекция будет возбуждать события ListChanged При изменении значений свойств ваших объектов, обусловленном действиями, произведенными через дескрипторы свойств — именно так производятся все обновления свойств через привязанные элементы управления, поддерживающие редактирование. Интерфейс имеет единственный элемент — булево свойство RaiseltemChangedEvents. Если коллекция возвращает в этом свойстве True, Потребляющий код вправе ожидать, что он будет получать уведомления в случае, когда какой-то объект в коллекции изменяется через привязанный элемент управления. Это используется во внутреннем устройстве компонента BindingSource Для лучшей синхронизации данных, отображаемых в привязанных элементах управления, даже если нижележащие объекты сами по себе не поддерживают уведомления об изменении свойств. Чтобы реализовать поддержку возбуждения событий ListChanged В ответ на изменения значений свойств в коллекции объектов, вам потребуется передать дескриптору свойства возвратно вызываемый делегат для каждого свойства каждого объекта в коллекции, так что коллекция будет получать уведомления об изменении этих свойств через дескриптор свойства. Это делается при помощи метода AddValueChanged Класса PropertyDescrriptor. Пример и более подробное обсуждение смотрите в главе 9, где реализуется класс Binding — ListView.