1. Построение приложений с привязанными данными в Windows Forms

Поиск в источнике данных через источник привязки

b метод принимает имя свойства

Для поиска в источнике данных через источник привязки вы можете вызвать на источнике привязки метод Find. Метод принимает имя свойства и ссылку типа Object. Имя свойства указывает, какое из свойств каждого из объектов в коллекции данных следует проверять, а ссылка на Object Содержит значение, которое требуется в нем найти. При обнаружении в списке первого элемента, у которого указанное свойство соответствует указанному значению, метод возвращает его индекс. Для правильной работы метода необходимо, чтобы источник данных поддерживал IBindingList И возвращал True В свойстве IBindingList. SupportsSearching. Использование метода Find Иллюстрируется следующим примером.

Этот код производит поиск по свойству CompanyName Во всех элементах списка, поддерживаемого источником привязки, отыскивая элемент со значением, соответствующим переданному в метод. Обратите внимание, что не делается никаких предположений относительно типа источника данных или его объектов. Этот метод одинаково хорошо работал бы и С CustomersDataTable Или коллекцией рабочих объектов Customer, При условии, что эта коллекция реализует IBindingList С поддержкой поиска. В главе 9 приводится пример того, как предусмотреть в своей коллекции такую поддержку.

Если опорная коллекция данных реализует интерфейс IBindingListView И возвращает True В свойстве IBindingListView.SupportsFiltering, То в свойстве Filter Источника привязки можно установить выражение фильтра. Если это сделать, то через источник привязки будут доступны только данные, отфильтрованные в соответствии с указанным критерием. При определенных характеристиках источника данных этот механизм может работать аналогично фильтрации DataView В ADO. NET. Конкретный синтаксис и степень сложности выражений, поддерживаемые фильтром, определяются источником данных. Выражение фильтра просто передается через источник привязки источнику данных, который и осуществляет фильтрацию, как показано в следующем примере:

Возбуждение событий изменения элемента

b в нем определено единственное

Есть еще один интерфейс, реализованный в классе BindingList<T>, Который вы, возможно, захотите переопределить в своих классах специальных коллекций для развитых сценариев: интерфейс IRaiseitemChangedEvents. В нем определено единственное булево свойство RaisesItemChangedEvents. В реализации класса BindingList<T> Это свойство возвращает False, Но вы можете при желании переопределить его в производном классе. Если вы возвращаете True, Показывая, что вы возбуждаете события изменения элемента, ожидается, что при изменении элементов в вашей коллекции вы будете возбуждать событие ListChanged. Если элементы вашей коллекции реализуют интерфейс INotifyPropertyChanged, Как было описано выше, это будет происходить автоматически. Но вы можете все равно поддерживать события изменения элемента, даже если объекты вашей коллекции и не поддерживают INotifyProperetyChanged. Однако к реализации IRaiseitemChangedEvents Следует подходить с осторожностью: для больших коллекций она может значительно ухудшить производительность, так как вы должны рефлектировать каждый объект при добавлении его в вашу коллекцию. В результате вызова AddValueChanged Метод, на который указывает делегат, будет вызываться всякий раз, когда значение свойства объекта изменяется посредством вызова метода SetValue Дескриптора свойства, а именно так привязанные к данным элементы управления редактируют источник данных. Все это будет совершенно бесполезно, если какой-то код получит ссылку на объект и будет устанавливать свойство через его установщик в определении свойства. Однако возвратный вызов будет активировать целевой метод всякий раз, когда свойство изменяется через привязанный элемент управления, поскольку именно через дескриптор привязанные элементы управления устанавливают свойства, не имея информации времени компиляции об объектах, к которым они привязаны. Следующий код показывает дополнительные методы, введенные в Binding — Listview<T> для поддержки уведомлений об изменении элемента. Класс BindingList<T> Уже реализует IRaiseitemChangedEvents, Но возвращает False, Указывая на отсутствие поддержки. Чтобы показать, что вы добавили поддержку, вам нужно реализовать интерфейс заново и возвратить True

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

генерируемый конструктором код будет содержать

Элементы управления имеют значения по умолчанию для всех свойств, которые они экспонируют, и именно эти значения будут использоваться в случае, если не установлено явно никакого другого значения. Генерируемый конструктором код будет содержать только тот код для установки свойств, где устанавливаются значения, отличные от значений по умолчанию. Например, когда вы ранее кодировали класс формы вручную и запускали приложение, строка заголовка была пуста, поскольку вы не установили свойство Text самой формы. Когда вы создаете форму в конструкторе, он сначала автоматически устанавливает в свойстве Text имя формы, и именно оно отображается в строке заголовка и в конструкторе, и во время исполнения. Вы можете изменить это свойство, как и любое другое, либо через окно Properties, либо программно. Значения свойств, которые были установлены равными чему-то иному, чем значения по умолчанию, будут выделены в окне Ptroperties жирным шрифтом. Как указывает комментарий к методу InitializeComponent, вы должны избегать непосредственной модификации кода этого метода. Масса этого кода переписывается всякий раз, когда вы модифицируете что-то на вашей форме в конструкторе. Поэтому в зависимости от характера кода, который вы добавляете или модифицируете в методе, ваши модификации могут быть утеряны, когда вы в следующий раз поправите что-то в конструкторе. Так что закройте этот файл, если он у вас открыт; я только хотел, чтобы вы получили возможность заглянуть в то, что происходит за кулисами. Как упоминалось выше, первое, что делает конструктор формы — это вызывает метод InitializeComponent, чтобы привести все элементы управления в то начальное состояние, которое вы специфицировали посредством визуального конструктора. Если вы хотите программно как-то иначе установить свойства или инициализировать другие элементы, которые не были объявлены посредством операций перетаскивания, то можете ввести в конструктор формы любой специальный код инициализации после вызова InitializeComponent.

Если вы совершенный новичок в программировании Windows Forms и в Visual Studio, этот пример мог показаться вам гораздо более сложным, чем простое написание кода вручную, из-за описания особенностей различных окон, визуального конструктора и кода, генерируемого в результате действий в конструкторе. Но фактом является то, что для многих вещей, которые вам придется делать в программировании Windows Forms, вы сможете достигнуть результата при помощи конструктора гораздо быстрее, чем вы написали бы весь код вручную, особенно, когда вы станете более уверенно и удобно чувствовать себя в работе с конструктором и IDE.

Свойство AllowEdit

этот обработчик производит простые проверки

Свойство AllowEdit Извлекает или устанавливает соответствующее свойство инкапсулированной коллекции BindingList, Которое проверяет обработчик события щелчка мыши, чтобы решить, следует ли производить обработку редактирования. Этот обработчик производит простые проверки на попадание щелчка в прямоугольники, вычисленные и сохраняемые методом UpdateCoordinates, И если он видит, что щелчок произошел внутри одного из столбиков, то увеличивает или уменьшает его значение на 10 процентов в зависимости от того, какая кнопка произвела щелчок. Теперь нужно добавить соответствующую поддержку в элемент управления DataBoundBarChartControl, Чтобы обновлять соответствующий источник данных, если это необходимо, и управлять редактируемостью отдельных элементов управления BarChartControl. Модифицированные фрагменты кода элемента управления выделены в листинге 8.12 жирным шрифтом.

Для отслеживания информации, достаточной для изменения привязанного списка данных при изменениях внутри отдельного экземпляра BarChartControl, Было добавлено несколько новых элементов класса: Ссылка на сам привязанный список, чтобы избежать многократного разрешения этой ссылки через синхронизатор. Когда источник данных обновляется и вызывается метод UpdateDataBinding, Вы сохраняете ссылку на привязанный список и устанавливаете флаг, показывающий, является ли источник обновляемым, исходя из состояния либо флага IList. IsReadOnly, Либо свойства IBindingList. AllowEdit В зависимости от того, реализует ли источник данных интерфейс IBindingList. При добавлении каждого элемента управления BarCharControl К вашему списку Controls Инкапсулирующий элемент управления подписывается на его событие DataValueChanged И устанавливает его редактируемость в зависимости от редактируемости списка. Наконец, обработчик для события DataValueChanged Любого из инкапсулированных диаграммных элементов управления, используя объектную ссылку на отправителя и индекс измененного столбика, обращается обратно к этому элементу управления, извлекает изменившееся значение, находит соответствующий объект в привязанном списке данных по индексу, сохраняемому для этого элемента управления в Hashtable, И устанавливает значение соответствующего свойства этого объекта в зависимости от действительного типа значения.

Класс Sort Comparer

b когда класс b list

Класс SortComparer Обеспечивает базовую реализацию сравнения, которая должна использоваться с методом List.Sort. Класс SortComparer Позволяет конструировать экземпляр класса, специфицировав свойство объектов, которое будет сравниваться для определения отношений «равно», «больше» или «меньше», передаваемое в дескрипторе свойства, и значение из перечисления ListSortDirection. Когда класс List<T> Производит итерацию по списку, применяя внутренний алгоритм сортировки, он вызывает метод Compare, Передавая ему два объекта, с которыми он в данный момент работает в процессе сортировки. Реализация Compare Из листинга 9.4 пробует различные способы сравнения объектов. Сначала она извлекает значение специфицированного свойства каждого из объектов при помощи метода Getvalue Дескриптора свойства. Затем она проверяет, реализует ли объект, который представляют эти значения, интерфейс IComparer. Это стандартный интерфейс в. NET Framework. Он реализует метод CompareTo, Инкапсулирующий ту же логику, к которой мы стремимся — говоря конкретнее, если объект сам решает, что он равен другому переданному объекту, он возвращает О; если он больше, он возвращает 1; если он меньше, он возвращает —1. Если значения свойства не реализуют IComparer, Но метод Equals Значения говорит, что оно равно другому объекту, то Compare Возвращает О, сообщая о равенстве. Наконец, если ни одна из проверок не удалась, значения свойства преобразуются в строки и строковые представления сравниваются при помощи CompareTo, Который реализует класс String. Самое последнее, что делает метод — проверяет направление сортировки, и если оно указывает на нисходящую сортировку, он умножает возвращаемое значение на — 1, чтобы обратить смысл отношений больше/меньше. Чтобы производить сортировку из вашего класса BindingListview<T>, Вам необходимо предусмотреть переопределения всех относящихся к сортировке методов и свойств базового класса. Они показаны в листинге 9.5.

Объявление переменной типа List<T> Для сохранения несортированной коллекции при применении сортировки.