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

Целесообразность композитного элемента управления

вы можете инкапсулировать расположение и

В сценарии такого рода целесообразность композитного элемента управления, производного от UserControl, представляется очевидной. Вы можете инкапсулировать расположение и обработку событий от группы элементов управления в своем специальном композитном элементе управления, а затем добавить его при надобности на любую форму или несколько форм. Вам придется сопровождать всего одну логическую единицу кода, и у вас будет развитая поддержка конструктора для создания элемента управления и добавления его к другим формам. См. пример реализации специального пользовательского элемента управления в разделе «Создание специального пользовательского элемента управления» настоящего приложения. Формы имеют специфический период жизни, с которым вам необходимо познакомиться. Как и все классы в. NET, формы и элементы управления имеют конструктор, где вы будете размещать основную часть инициализации элементов класса и дочерних элементов управления. Формы и элементы управления следуют модели. NET, реализуя интерфейс IDisposable, который предусматривает для клиентов класса единообразный способ сообщить классу, что они закончили с ним работать, позволяя ему, таким образом, освободить любые автономные ресурсы, которые он содержит. В формах и элементах управления имеется реализация базового класса для метода Dispose, которую вы можете переопределить, чтобы предусмотреть любой специальный код очистки для автономных ресурсов, которые может инкапсулировать ваша форма. Если вы переопределяете метод Dispose, этот код будет вызываться Framework при закрытии формы. Вы никогда не должны забывать вызвать реализацию Dispose вашего базового класса, чтобы дать ему возможность освободить те ресурсы, которые он инкапсулирует. Файл кода конструктора Windows Forms в Visual Studio 2005 содержит переопределение метода Dispose, и если вам нужно гарантировать, что ваши собственные элементы-переменные уничтожаются, вам нужно будет добавить соответствующий код в этот метод в файле кода конструктора.

Интерфейс 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 Уведомляет элементы управления о добавлениях, удалениях и изменениях элементов в привязанной коллекции, а элементы управления могут использовать эти уведомления для своего обновления в соответствии с состоянием источника данных.