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

Присоединение динамического поведения в классе кода поддержки

чтобы воспользоваться контекстной вкладкой нужно

После того, как вы специфицировали планировку страницы в ASPX-файле разметки, вы подключаете к странице динамическое поведение, определяя файл кода поддержки, как показано в листинге А.2.

Код поддержки для данного примера, показанный в листинге А. 2, типичен для простой Web-формы ASP. NET 1.1. Любые серверные элементы управления, определяемые в разметке ASPX-файла, включаются также в класс кода поддержки в качестве элемент-переменных. Сопоставляя имя элемент-переменной с тегом ID в файле ASPX, исполнительная система ASP. NET ассоциирует с этими переменными элемент управления, созданный по коду разметки во время исполнения. Элемент-переменные класса кода поддержки могут использоваться для программного доступа и модификации этих элементов управления при обработке страницы. Здесь можно видеть один дополнительный элемент для типизированного набора данных NorthwindDataSet, Которого нет в разметке страницы. Он был добавлен путем перетаскивания с инструментальной панели на страницу элемента DataSet В конструкторе, но поскольку он не имеет собственного визуального представления, то не добавляет ничего к разметке, а только к поддерживающему коду. Большинство страниц ASP. NET проделывают большой объем обработки в своем обработчике события Page.Load, Который в Visual Studio по умолчанию именуется Page Load. Это часто будет тем самым местом, где вы будете производить извлечение данных, необходимых странице для своего отображения, и будете сохранять эти данные в элемент-переменных, чтобы они были доступны для других методов страницы, которые вызываются при ее обработке. Помните, что для каждого входящего запроса создается новый экземпляр страницы, так что элемент-переменные находятся в области действия только в течение обработки единственного запроса. Кроме того, у вас может быть любое число дополнительных вспомогательных методов, чтобы вынести в них код, инициализирующий элементы управления страницы и их переменные, и любое число обработчиков для событий, возбуждаемых элементами управления при отсылках. Обычно вы будете выполнять первичную инициализацию отображения элементов управления на странице в обработчике Page Load, А затем производить большую часть обработки отсылок в обработчиках событий для элементов управления, хотя можно также выполнять часть обработки при отсылках в Page Load, Если для вашего сценария это целесообразно.

Манипулирование данными посредством источника привязки

после того как вы установите

Источник привязки сам по себе предоставляет вам косвенный доступ к данным, хранящимся в нижележащем источнике данных на стороне клиента. После того, как вы установите свойство DataSource Источника привязки, вам более не потребуется хранить ссылку на сам источник данных, поскольку она будет сохраняться источником привязки. И вы всегда можете получить ссылку на источник данных путем приведения значения свойства DataSource К ожидаемому типу. Единственный недостаток подобного подхода заключается в том, что в той точке кода, где вы используете ссылку из DataSource, Вы должны точно знать тип коллекции данных, к которому прикрепляется источник привязки. Ключ ко всей концепции — в понимании того, что в качестве источника данных для родительского источника привязки необходимо установить родительскую коллекцию объектов, а в качестве источника данных для дочернего источника привязки — ссылку на родительский источник привязки. Тогда свойство DataMember Дочернего источника привязки должно быть именем свойства в родительском объекте, которое является ссылкой на дочернюю коллекцию. Здесь это свойство Children, Принадлежащее к типу Binding — List<ChildObject>. При этом BindingList Является обобщенным типом коллекций, предусмотренным в. NET 2.0 специально для привязки данных в Windows Forms, a ChildObject — это тип-параметр коллекции, специфицирующий тип объектов, которые будет содержать коллекция. Используя эту методику каскадирования источников привязки, вы можете поддерживать иерархии родительских и дочерних данных произвольной глубины. Вы, кроме того, всегда можете получить текущий элемент данных в коллекции через свойство Current Источника привязки. Свойство Current Возвращает ссылку на объект, и, если вы знаете типы всех элементов коллекции, вы опять же можете выполнить соответствующее приведение типа и работать с элементами данных. Помните, что тип объекта, возвращаемого свойством Current, Всегда будет DataRowView Во всех случаях, когда вы привязываетесь к DataTable Или DataView, И это будет экземпляр какого-то объектного типа, хранящегося в коллекции, если вы работаете со специальными объектами.

Закрепление элементов управления

возможно вы хотите чтобы элемент

Для многих видов элементов управления и планировок формы вам хотелось бы, чтобы элементы управления сохраняли одно и то же положение относительно одной или нескольких сторон формы. Возможно, вы хотите, чтобы элемент управления сохранял свой размер, но оставался в том же положении относительно двух смежных сторон формы, например, левого верхнего или правого нижнего угла формы. Либо вы хотите, чтобы внешние кромки элемента управления сохраняли свое положение относительно противоположных сторон формы, т. е. чтобы он растягивался или сжимался при расширении или сокращении формы. Взгляните, например, на рис. В.14 — это одна и та же форма, но она показана при различных размерах. Для подобных форм вы, вероятно, захотите, чтобы при изменении размера сетка данных заполняла все наличное пространство формы, не используемое кнопками. Вы также, вероятно, хотели бы, чтобы кнопка в левом нижнем углу оставалась в фиксированном положении относительно этого угла, и то же самое касается кнопки справа внизу. Наконец, вы, вероятно, хотели бы, чтобы средняя кнопка оставалась по центру формы и в фиксированном положении относительно ее нижней кромки, можно видеть, Посмотрев на размеры сетки и положение кнопок на рис. В. 14, вы увидите, что можно достичь именно такого поведения, не написав вручную ни единой строки кода, а просто установив соответствующим образом свойство Anchor Каждого из элементов управления в окне Properties. Свойство Anchor Принимает перечисление типа AnchorStyles, Которое имеет флаговые значения Top, Bottom, Left И Right. Поскольку это флаговое перечисление, вы можете объединять эти значения посредством булевой операции «или» . Конструктор Visual Studio предоставляет вам удобный графический редактор для этого свойства, показанный на рис. В. 15, который позволяет визуально выбрать стороны, у которых вы хотите закрепить элемент управления. Получающийся при этом код эквивалентен следующему коду для закрепления сетки у всех четырех сторон, чтобы она изменяла размер так, что каждая из ее четырех сторон сохраняла бы свое положение относительно соответствующей стороны формы:

Набор данных с установленным родительско-дочерним отношением

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

Как только у вас будет набор данных с установленным родительско-дочерним отношением, можно строить форму. Вы можете либо просто прочитать нижеприведенные инструкции, либо, если захотите проделать все это сами, создайте сначала проект Windows Application и поместите на форму два элемента управления DataGridView, два BindingSource и один BindingNavigator. Одна сетка предназначена для родительской коллекции данных, вторая отображает дочерние строки. В приложении MasterDe — tailsSample, код которого можно загрузить, эти данные поступают соответственно из таблиц Customers и Orders. Первый источник привязки служит просто для заполнения родительской сетки из таблицы Customers, аналогично тому, что вы видели в предыдущих примерах. Трюк, заставляющий работать сценарий «ведущий-детализация», состоит в том, что в свойстве DataSource дочернего источника привязки вы устанавливаете родительский источник привязки — в MasterDetailsSample это m CustomersBindingSource. Затем вы специфицируете имя отношения данных, которое соотносит родительские строки с дочерними, в качестве значения свойства DataMember родительского источника привязки; в следующим Вот и все. Каскадирование дочернего источника привязки с родительским автоматически синхронизирует текущую строку в родительской коллекции с набором соответствующих дочерних строк в дочерней коллекции. Тем не менее, если вам требуется сохранить эти изменения из привязанного источника на уровне хранения данных, то придется написать соответствующий код доступа к данным. Обычно такой код выполняется в ответ на щелчок пользователя на кнопке панели инструментов, командной кнопке, на выбор команды в меню, и для этого достаточно вызвать метод Update соответствующего адаптера таблицы. В следующем листинге приведен обновляющий код, генерируемый конструктором для кнопки Save элемента управления Вызов Validate обеспечивает выполнение верификации для последнего элемента управления, который обладал фокусом ввода. Вызов EndEdit фиксирует все внесенные изменения в текущем источнике данных, если этот объект поддерживает транзакционные обновления через интерфейс

Объект SqlCommand

объекту команды можно передать либо

Как только у вас есть соединение, с которым можно работать, вы создаете объект SqlCommand, Передавая конструктору текст запроса SQL для исполнения и соединение, которое следует использовать. Объекту команды можно передать либо операторы SQL, либо имя сохраняемой процедуры. В реальных уровнях данных я рекомендую инкапсулировать доступ к данным на уровне базы данных в сохраняемых процедурах, и в своем уровне данных лишь потреблять эти процедуры. Это развяжет код вашего приложения от специфической схемы ваших таблиц, благодаря чему небольшие изменения в нижележащей схеме не будут влиять на код приложения. Сохраняемые процедуры позволят вам также использовать встроенные механизмы безопасности SQL Server для предотвращения прямого доступа к таблицам, и сохраняемые процедуры обеспечивают иногда лучшую производительность, чем динамические операторы SQL, исполняемые из кода в листинге Г. З. Во многих примерах кода в этой книге я нарушал эту рекомендацию, чтобы можно было использовать базу данных Northwind с минимальными модификациями, и чтобы вы ясно могли видеть, что именно извлекается запросами При выполнении текстовых запросов SQL Вы должны точно специфицировать столбцы, которые должны возвращаться вашим запросом. Спецификация * для столбцов может возвратить гораздо больше информации, чем вам нужно, влияя на производительность приложения. При этом объекту команды требуется проделать больше работы для определения точной схемы результирующего набора, который будет возвращен запросом Создает объект SqlDataAdapter, Являющийся мостом между нейтральным в смысле источника набором данных и специфическим источником данных, с которым он будет работать. В данном слу-чае я конструирую его, передавая объект команды.