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

Интерфейс ICancelAddNew: поддержка транзакционных вставок в коллекцию

этот интерфейс был введен в

Интерфейс ICancelAddNew Позволяет добавлять в коллекцию и редакти ровать новые элементы в промежуточном состоянии, допускающем удаление нового элемента до окончательного утверждения изменений. Этот интерфейс был введен в .NET 2.0, чтобы разорвать неявную взаимозависимость, возникающую в интерфейсе LEditableObject. До определения ICancelAddNew Объекты коллекции, реализующей интерфейс LEditableObject, Должны были уведомлять свою родительскую коллекцию об отмене редактирования вновь добавляемого элемента, чтобы коллекция могла удалить этот элемент. При использовании ICancelAddNew Коллекция может сама позаботиться об удалении, и объект не должен теперь иметь прямую связь с содержащей его коллекцией, чтобы отменить добавление нового элемента при отмене его инициализации. Другой возможностью, которая напрашивается для расширения возможностей привязки данных, является поддержка транзакционных вставок элементов в коллекцию. Чтобы в этом разобраться, рассмотрим таблицу данных, привязанную к сетке. Сетка отображает внизу пустую строку, позволяющую добавлять к таблице новые строки. Но что, если имеются ограничения на столбцы этой строки, или требуется совместная верификация значений, введенных в нескольких полях, прежде чем можно будет добавить элемент к коллекции данных? Как можно предотвратить добавление в коллекцию несогласованных данных? В конце концов, где-то ведь должен быть экземпляр объекта, который принимает вводимые пользователем данные по мере того, как тот переходит от одного поля к другому. Наиболее логичным представляется создание такого объекта в качестве новой строки в источнике данных. Но вы не хотите фактически добавлять этот объект, пока его добавление не будет признано «законченным», что бы это ни означало в контексте конкретной коллекции и объектов внутри нее.

Метод Main

допустим например что приложение должно

Для некоторых приложений вам может потребоваться модифицировать метод Main, Чтобы он выполнял какие-то другие формы инициализации приложения, прежде чем оно будет запущено. Допустим, например, что приложение должно принимать единственный параметр командной строки, который соответствует режиму работы приложения. Класс главной формы можно было бы модифицировать так, чтобы он передавал этот параметр своему конструктору, чтобы тот инициализировал его значением элемент-переменную. В этом случае можно было бы модифицировать метод Main Следующим образом:

В этом примере вы проверяете переданные аргументы, чтобы убедиться в том, что получили ожидаемое. Затем вы передаете первую строку массива конструктору класса вашей формы. Вы, естественно, должны были бы модифицировать или перегрузить конструктор формы, чтобы он для полноты сценария принимал строковый аргумент, и этот конструктор, вероятно, устанавливал бы в зависимости от этого параметра значение элемента-поля. Другой распространенной модификацией метода Main Была бы установка глобального обработчика исключений для вашего приложения Windows Forms, чтобы неперехваченные исключения не всплывали наверх к исполнительной системе и не заставляли ваше приложение умереть, представляя пользователю во время исполнения лишь малоутешительный диалог. Если вы перед вызовом метода Run В методе Main Добавите обработчик для исключения ThreadException Класса Application, То этот обработчик будет вызываться всякий раз, когда исключение всплывает на вершину стека не перехваченным. В своем обработчике вы можете проделать любую регистрацию ошибки, какую сочтете необходимой, и можете представить пользователю несколько более дружелюбный диалог, какой сможете придумать. Затем вам решать, закрывать приложение или нет, как показывает следующий код:

Способ каким вы обрабатываете события элементов управления

вам нужно подписаться на событие

Способ, каким вы обрабатываете события элементов управления, не отличается от обработки любого другого события. NET. Вам нужно подписаться на событие, используя встроенные механизмы выбранного вами. NET-языка. В C# вы подписываетесь на событие при помощи операции +=, передавая экземпляр соответствующего типа делегата, инициализированный указателем на метод обработчика события:

Другой нотацией, о которой вам следует знать, является новый синтаксис C# 2.0 для Неявных делегатов . В вышеприведенном коде я явным образом создал новый экземпляр типа делегата для данного события, EventHandler, И передал его операции +=. В C# 2.0 компилятор достаточно сообразителен, чтобы вывести соответствующий тип делегата по типу события, на которое вы организуете подписку. Поэтому в C# 2.0 вы можете сократить нотацию до простого указания метода обработчика: Хотя я и не включаю в текст каких-либо примеров на Visual Basic, код всех образцов на Visual Basic можно загрузить с сайта. Поскольку синтаксис обработки событий — это одно из немногих мест, где код Visual Basic совершенно отличается от его эквивалента на С#, вот пример на Visual Basic. В Visual Basic вы можете воспользоваться ключевым словом AddHandler, Передав событие и метод обработчика: В Visual Basic вы можете также объявить экземпляр элемента управления при помощи ключевого слова WithEvents, А затем воспользоваться модификатором Handles В конце объявления метода, чтобы подключить его в качестве обработчика события:

Синхронизация данных между элементами управления

как мы уже упоминали когда

Давайте взглянем теперь на то, что происходит, когда вы привязываете элемент управления или несколько элементов управления на форме к набору данных. Как мы уже упоминали, когда вы создаете привязки данных, форма сама создает синхронизирующие объекты на тот случай, если некоторые из ваших элементов управления будут привязаны к одному источнику данных и вы хотите, чтобы они были синхронизированы. Сама форма имеет свойство BindingContext, Содержащее коллекцию синхронизирующих объектов для каждого из источников данных, используемых для привязки на этой форме. Как правило, в. NET 2.0 вам нет нужды в своем коде иметь дело непосредственно с контекстом привязки, но иногда, чтобы все заработало, необходимо именно понимание скрытых от вас процессов. . Как говорилось в предыдущем разделе, скрытым образом создаются экземпляры CurrencyManager Для списочных источников данных или PropertyManager Для индивидуальных объектов. Каждый из этих классов производится ОТ BindingManagerBase; В BindingContext СОДержится ссылка на объект именно этого типа. Чаще всего вам придется иметь дело С CurrencyManager. Компонент-контейнер Создает экземпляр CurrencyManager Для каждого списочного источника данных, который вы специфицировали для элемента управления на форме, и добавляет его в контекст привязки формы. CurrencyManager Отслеживает как источник данных, так и привязанные к его данным элементы управления. Вы можете использовать его для доступа к данным, стоящим за элементами управления, определять текущую строку или объект и изменять эту текущую строку, воздействуя тем самым на все привязанные к ней элементы управления. CurrencyManager Уведомляет элементы управления о добавлениях, удалениях и изменениях элементов в привязанной коллекции, а элементы управления могут использовать эти уведомления для своего обновления в соответствии с состоянием источника данных.

Элементарная привязка данных в DataGridView

для этого вам прежде всего

Наилучший способ приступить к изучению элемента управления DataGridView — это использовать его в элементарных сценариях привязки данных. Для этого вам прежде всего нужно получить коллекцию данных, что обычно делается через рабочий уровень или уровень доступа к данным вашего приложения. Затем вы устанавливаете свойства привязки данных сетки, чтобы привязаться к коллекции данных, как было описано в главах 4 и 5. Как и в случае других элементов управления Windows Forms, в. NET 2.0 рекомендуется всегда привязывать действительный источник данных на стороне клиента к объекту BindingSource, А уже к нему привязывать элементы управления. Этот процесс иллюстрируется следующим кодом. В элементарных сценариях привязки данных DataGridView Функционирует точно так же, как элемент управления DataGrid В. NET 1.0, за исключением того, что комбинация свойств DataSource И DataMember Должна определять коллекцию элементов данных, такую, как таблица или коллекция объектов. Говоря точнее, эти свойства должны определять объект, реализующий интерфейс IList. Сетка DataGrid Могла быть привязана к коллекции коллекций, такой, как DataSet, И в этом случае отображала элементы управления иерархической навигации для перемещения по коллекциям данных. Однако такая возможность использовалась редко, отчасти потому, что навигационные элементы управления, отображаемые в сетке, не были интуитивно понятны и могли дезориентировать пользователя. Поэтому группа Windows Client, разрабатывавшая DataGridView, Решила не поддерживать иерархическую навигацию в самом элементе управления. Сетка DataGridView Предназначена для представления одновременно только одной коллекции данных. Вы все равно можете осуществить наглядную иерархическую навигацию в данных, но для этого используется, как правило, более одного элемента управления, с применением подхода «ведущий-детализация», описывавшегося в предыдущих главах.