Взаимодействие с эталонной страницей на странице содержимого (C#)

Скотт Митчелл

Проверяет, как вызывать методы, задавать свойства и т. д. эталонной страницы из кода на странице содержимого.

Введение

В ходе работы с последними пятью руководствами мы рассмотрели, как создать страницу master, определить области содержимого, привязать страницы ASP.NET к master странице и определить содержимое для конкретной страницы. Когда посетитель запрашивает определенную страницу содержимого, разметка содержимого и master страниц объединяется во время выполнения, что приводит к отображению единой иерархии элементов управления. Таким образом, мы уже видели один из способов взаимодействия страницы master и одной из ее страниц содержимого: страница содержимого описывает разметку для переливания в элементы управления ContentPlaceHolder master страницы.

Нам еще предстоит изучить, как страница master и страница содержимого могут взаимодействовать программными средствами. Помимо определения разметки для элементов управления ContentPlaceHolder страницы master, страница содержимого также может назначать значения общедоступным свойствам своей master страницы и вызывать ее открытые методы. Аналогичным образом страница master может взаимодействовать со страницами содержимого. Хотя программное взаимодействие между master и страницей содержимого является менее распространенным, чем взаимодействие между декларативными разметками, существует множество сценариев, в которых такое программное взаимодействие требуется.

В этом руководстве мы рассмотрим, как страница содержимого может программно взаимодействовать со своей master страницей. В следующем руководстве мы рассмотрим, как страница master может аналогичным образом взаимодействовать со своими страницами содержимого.

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

Если определенную область страницы необходимо настроить постранично, мы используем элемент управления ContentPlaceHolder. Но как насчет ситуаций, когда большинство страниц должны выдавать определенные выходные данные, а небольшое количество страниц нужно настроить, чтобы показать что-то другое? Один из таких примеров, который мы рассмотрели в учебнике Multiple ContentPlaceHolders and Default Content, включает отображение интерфейса входа на каждой странице. Хотя большинство страниц должно содержать интерфейс входа, он должен подавляться для нескольких страниц, таких как страница main входа (Login.aspx); страница Создания учетной записи и другие страницы, доступные только для пользователей, прошедших проверку подлинности. В учебнике Multiple ContentPlaceHolders and Default Content было показано, как определить содержимое по умолчанию для ContentPlaceHolder на странице master, а затем переопределить его на тех страницах, где содержимое по умолчанию не требуется.

Другой вариант — создать открытое свойство или метод на странице master, который указывает, следует ли отображать или скрывать интерфейс входа. Например, страница master может содержать открытое свойство с именем ShowLoginUI , значение которого использовалось для задания Visible свойства элемента управления Login на странице master. Страницы содержимого, на которых должен подавляться пользовательский интерфейс входа, могут программно задать ShowLoginUI для свойства значение false.

Возможно, наиболее распространенный пример взаимодействия с содержимым и master страницы происходит, когда данные, отображаемые на странице master, необходимо обновить после того, как на странице содержимого произошло какое-либо действие. Рассмотрим страницу master, включающую GridView, которая отображает пять последних добавленных записей из определенной таблицы базы данных и что одна из страниц содержимого содержит интерфейс для добавления новых записей в ту же таблицу.

Когда пользователь посещает страницу для добавления новой записи, он видит пять последних добавленных записей, отображаемых на странице master. После заполнения значений для столбцов новой записи она отправляет форму. Предположим, что свойство GridView на странице EnableViewState master имеет значение true (значение по умолчанию), его содержимое перезагружается из состояния представления и, следовательно, отображаются пять одинаковых записей, даже если в базу данных только что добавлена новая запись. Это может сбить с толку пользователя.

Примечание

Даже если вы отключите состояние представления GridView, чтобы оно повторно привязывалось к базовому источнику данных при каждой обратной отправке, оно по-прежнему не будет отображать только что добавленную запись, так как данные привязаны к GridView раньше в жизненном цикле страницы, чем при добавлении новой записи в базу данных.

Чтобы устранить эту проблему, чтобы только что добавленная запись отображалась в GridView страницы master при обратной отправке, необходимо указать GridView повторно привязыться к источнику данных после добавления новой записи в базу данных. Для этого требуется взаимодействие между содержимым и master страницами, так как интерфейс для добавления новой записи (и ее обработчики событий) находится на странице содержимого, а элемент GridView, который необходимо обновить, находится на странице master.

Так как обновление отображения страницы master из обработчика событий на странице содержимого является одной из наиболее распространенных потребностей в содержимом и master взаимодействии со страницей, давайте рассмотрим этот раздел более подробно. Скачивание этого руководства включает базу данных Microsoft SQL Server 2005, экспресс-выпуск с именем NORTHWIND.MDF в папке App_Data веб-сайта. В базе данных Northwind хранятся сведения о продуктах, сотрудниках и продажах для вымышленной компании Northwind Traders.

Шаг 1 содержит пошаговые инструкции по отображению пяти последних добавленных продуктов в GridView на странице master. На шаге 2 создается страница содержимого для добавления новых продуктов. На шаге 3 рассматривается создание открытых свойств и методов на странице master, а на шаге 4 показано, как программно интерфейсировать с этими свойствами и методами на странице содержимого.

Примечание

В этом руководстве не рассматривается особенности работы с данными в ASP.NET. Действия по настройке страницы master для отображения данных и страницы содержимого для вставки данных завершены, но не очень. Дополнительные сведения о отображении и вставке данных, а также использовании элементов управления SqlDataSource и GridView см. в ресурсах в разделе Дополнительные чтения в конце этого руководства.

Шаг 1. Отображение пяти последних добавленных продуктов на главной странице

Откройте страницу Site.master master и добавьте в элемент управления leftContent<div>Label и GridView . Очистите свойство Label Text , присвойте свойству EnableViewState значение false, а свойству ID — значение GridMessage; задайте для свойства GridView ID значение RecentProducts. Затем в Designer разверните смарт-тег GridView и привяжите его к новому источнику данных. Откроется мастер настройки источника данных. Так как база данных Northwind в папке App_Data является базой данных Microsoft SQL Server, выберите создать SqlDataSource, выбрав (см. рис. 1); назовите SqlDataSource RecentProductsDataSource.

Привязка GridView к элементу управления SqlDataSource с именем RecentProductsDataSource

Рис. 01. Привязка GridView к элементу управления SqlDataSource с именем RecentProductsDataSource (щелкните для просмотра полноразмерного изображения)

На следующем шаге нам нужно указать, к какой базе данных следует подключиться. NORTHWIND.MDF Выберите файл базы данных в раскрывающемся списке и нажмите кнопку Далее. Так как мы впервые используем эту базу данных, мастер предложит сохранить строка подключения в Web.config. Сохраните строка подключения с именем NorthwindConnectionString.

Подключение к базе данных Northwind

Рис. 02. Подключение к базе данных Northwind (щелкните, чтобы просмотреть полноразмерное изображение)

Мастер настройки источника данных предоставляет два способа, с помощью которых можно указать запрос, используемый для получения данных:

  • Путем указания пользовательской инструкции SQL или хранимой процедуры;
  • Путем выбора таблицы или представления, а затем указания возвращаемых столбцов

Так как мы хотим вернуть только пять последних добавленных продуктов, необходимо указать пользовательскую инструкцию SQL. Используйте следующий запрос SELECT:

SELECT TOP 5 ProductName, UnitPrice FROM Products ORDER BY ProductID DESC

Ключевое слово TOP 5 возвращает только первые пять записей из запроса. Первичный Products ключ таблицы — ProductIDэто IDENTITY столбец, который гарантирует, что каждый новый продукт, добавленный в таблицу, будет иметь большее значение, чем предыдущая запись. Таким образом, сортировка результатов по ProductID убыванию возвращает продукты, начиная с последних созданных.

Возврат пяти последних добавленных продуктов

Рис. 03. Возврат пяти последних добавленных продуктов (щелкните для просмотра полноразмерного изображения)

После завершения работы мастера Visual Studio создает два BoundField для GridView для отображения ProductName полей и UnitPrice , возвращенных из базы данных. На этом этапе декларативная разметка страницы master должна содержать следующую разметку:

<asp:Label ID="GridMessage" runat="server" EnableViewState="false"></asp:Label>
<asp:GridView ID="RecentProducts" runat="server" AutoGenerateColumns="False"
 DataSourceID="RecentProductsDataSource">
 <Columns> 
 <asp:BoundField DataField="ProductName" HeaderText="ProductName" 
 SortExpression="ProductName"/> 
 <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
 SortExpression="UnitPrice"/> 
 </Columns> 
</asp:GridView> 

<asp:SqlDataSource ID="RecentProductsDataSource" runat="server" 
 ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>" 
 SelectCommand="SELECT TOP 5 ProductName, UnitPrice FROM Products ORDER BY ProductID DESC"> 
</asp:SqlDataSource>

Как видите, разметка содержит: веб-элемент управления Label (GridMessage); GridView RecentProductsс двумя BoundFields и элемент управления SqlDataSource, который возвращает пять последних добавленных продуктов.

После создания этого элемента управления GridView и настройки элемента управления SqlDataSource посетите веб-сайт через браузер. Как показано на рисунке 4, в левом нижнем углу появится сетка с пятью последними добавленными продуктами.

GridView отображает пять последних добавленных продуктов

Рис. 04. GridView отображает пять последних добавленных продуктов (щелкните для просмотра полноразмерного изображения)

Примечание

Вы можете очистить внешний вид GridView. Некоторые рекомендации включают форматирование отображаемого UnitPrice значения в виде валюты и использование цветов фона и шрифтов для улучшения внешнего вида сетки.

Шаг 2. Создание страницы содержимого для добавления новых продуктов

Следующая задача — создать страницу содержимого, с которой пользователь может добавить новый продукт в таблицу Products . Добавьте новую страницу содержимого в папку Admin с именем AddProduct.aspx, обязательно привязав ее к Site.master странице master. На рисунке 5 показана Обозреватель решений после добавления этой страницы на веб-сайт.

Добавление новой страницы ASP.NET в папку Администратор

Рис. 05. Добавление новой страницы ASP.NET в папку Admin (щелкните для просмотра полноразмерного изображения)

Напомним, что в учебнике Указание заголовка, метатегов и других заголовков HTML главной страницы мы создали пользовательский класс базовой страницы с именем BasePage , который создал заголовок страницы, если он не был задан явным образом. Перейдите к классу AddProduct.aspx кода программной части страницы и наследуйте его от BasePage (а не от System.Web.UI.Page).

Наконец, обновите файл, Web.sitemap включив запись для этого урока. Добавьте следующую разметку под для <siteMapNode> урока Проблемы с именованием идентификатора элемента управления:

<siteMapNode url="~/Admin/AddProduct.aspx" title="Content to Master Page Interaction" />

Как показано на рисунке 6, добавление этого <siteMapNode> элемента отражено в списке Уроки.

Вернитесь к AddProduct.aspx. В элементе управления Контент для MainContent ContentPlaceHolder добавьте элемент управления DetailsView и назовите его NewProduct. Привяжите DetailsView к новому элементу управления SqlDataSource с именем NewProductDataSource. Как и в случае с SqlDataSource на шаге 1, настройте мастер таким образом, чтобы он использовал базу данных Northwind, и выберите, чтобы указать пользовательскую инструкцию SQL. Так как DetailsView будет использоваться для добавления элементов в базу данных, необходимо указать как оператор, SELECT так и INSERT оператор . Используйте следующий SELECT запрос:

SELECT ProductName, UnitPrice FROM Products

Затем на вкладке INSERT добавьте следующий INSERT оператор:

INSERT INTO Products(ProductName, UnitPrice) VALUES(@ProductName, @UnitPrice)

После завершения работы мастера перейдите к смарт-тегу DetailsView и проверка флажок "Включить вставку". При этом commandField добавляется в DetailsView со свойством ShowInsertButton true. Так как этот DetailsView будет использоваться исключительно для вставки данных, задайте свойству DetailsView DefaultMode значение Insert.

Вот и все! Давайте протестируем эту страницу. Посетите AddProduct.aspx браузер, введите имя и цену (см. рис. 6).

Добавление нового продукта в базу данных

Рис. 06. Добавление нового продукта в базу данных (щелкните для просмотра полноразмерного изображения)

Введя имя и цену для нового продукта, нажмите кнопку Вставить. Это приводит к обратной отправке формы. При обратной отправке выполняется инструкция элемента управления INSERT SqlDataSource; два его параметра заполняются введенными пользователем значениями в двух элементах управления TextBox DetailsView. К сожалению, нет визуальной обратной связи о том, что вставка была выполнена. Было бы неплохо отобразить сообщение с подтверждением того, что добавлена новая запись. Я оставляю это как упражнение для читателя. Кроме того, после добавления новой записи из элемента DetailsПросмотреть GridView на странице master по-прежнему отображаются те же пять записей, что и раньше. Она не включает только что добавленную запись. Мы рассмотрим, как устранить эту проблему в следующих шагах.

Примечание

Помимо добавления визуальной обратной связи о том, что вставка выполнена успешно, рекомендуется также обновить интерфейс вставки DetailsView, чтобы включить проверку. В настоящее время проверка не выполняется. Если пользователь вводит недопустимое значение для UnitPrice поля, например "Слишком дорого", при обратной отправке создается исключение, когда система попытается преобразовать строку в десятичное число. Дополнительные сведения о настройке интерфейса вставки см. в руководстве По настройке интерфейса изменения данных из серии учебников По работе с данными.

Шаг 3. Создание открытых свойств и методов на главной странице

На шаге 1 мы добавили веб-элемент управления Label с именем GridMessage над GridView на странице master. Эта метка при необходимости предназначена для отображения сообщения. Например, после добавления новой записи в таблицу Products может потребоваться отобразить следующее сообщение: "ProductName добавлен в базу данных". Вместо жесткого написания текста для этой метки на странице master может потребоваться настроить сообщение на странице содержимого.

Так как элемент управления Label реализуется как защищенная переменная-член на странице master, доступ к нему напрямую со страниц контента невозможен. Для работы с меткой на странице master со страницы содержимого (или любого веб-элемента управления на странице master) необходимо создать на странице master открытое свойство, которое предоставляет веб-элемент управления или служит прокси-сервером, с помощью которого можно получить доступ к одному из его свойств. Добавьте следующий синтаксис в класс кода программной части страницы master, чтобы предоставить свойство LabelText:

public string GridMessageText 
{ 
    get
    { 
        return GridMessage.Text; 
    } 
    set 
    {
        GridMessage.Text = value; 
    }
}

При добавлении новой записи в таблицу Products со страницы RecentProducts содержимого GridView на странице master необходимо повторно привязываться к базовому источнику данных. Чтобы повторно привязать GridView, вызовите его DataBind метод . Так как Элемент GridView на странице master программно недоступен для страниц содержимого, необходимо создать открытый метод на странице master, который при вызове повторно привязывал данные к GridView. Добавьте следующий метод в класс кода программной части страницы master:

public void RefreshRecentProductsGrid() 
{ 
    RecentProducts.DataBind();
}

При наличии GridMessageText свойства и RefreshRecentProductsGrid метода любая страница содержимого может программно задать или прочитать значение GridMessage свойства Label Text или повторно привязать данные к RecentProducts GridView. На шаге 4 рассматривается доступ к общедоступным свойствам и методам страницы master со страницы содержимого.

Примечание

Не забудьте пометить свойства и методы страницы master как public. Если явно не обозначить эти свойства и методы как public, они не будут доступны на странице содержимого.

Шаг 4. Вызов открытых участников главной страницы из страницы содержимого

Теперь, когда страница master содержит необходимые открытые свойства и методы, мы готовы вызывать эти свойства и методы со страницы содержимогоAddProduct.aspx. В частности, необходимо задать свойство страницы GridMessageText master и вызвать его RefreshRecentProductsGrid метод после добавления нового продукта в базу данных. Все ASP.NET веб-элементы управления данными запускают события непосредственно перед и после выполнения различных задач, что упрощает для разработчиков страниц выполнение некоторых программных действий до или после задачи. Например, когда пользователь нажимает кнопку Вставить DetailsView, при обратной отправке DetailsView вызывает событие ItemInserting перед началом рабочего процесса вставки. Затем он вставляет запись в базу данных. После этого DetailsView вызывает событие ItemInserted . Поэтому для работы со страницей master после добавления нового продукта создайте обработчик событий для события DetailsViewItemInserted.

Существует два способа программного взаимодействия страницы содержимого со страницей master:

  • Page.Master Использование свойства , которое возвращает слабо типизированные ссылки на страницу master, или
  • Укажите master тип страницы или путь к файлу @MasterType с помощью директивы . Это автоматически добавляет строго типизированное свойство на страницу с именем Master.

Рассмотрим оба подхода.

Использование слабо типизированногоPage.Masterсвойства

Все ASP.NET веб-страницы должны быть производными Page от класса , расположенного System.Web.UI в пространстве имен . Класс Page содержит Master свойство , возвращающее ссылку на страницу master страницы. Если на странице нет master страница Master возвращает значение null.

Свойство Master возвращает объект типа MasterPage (также расположенный System.Web.UI в пространстве имен), который является базовым типом, от которого являются все master страницы. Таким образом, чтобы использовать открытые свойства или методы, определенные на странице master веб-сайта, необходимо привести MasterPage объект, возвращенный из Master свойства, к соответствующему типу. Так как мы назвали файл master страницы Site.master, класс кода программной части был назван Site. Таким образом, следующий код приводит Page.Master свойство к экземпляру класса Site.

// Cast the loosely-typed Page.Master property and then set the GridMessageText property 
Site myMasterPage = Page.Master as Site;

Теперь, когда мы приведения слабо типизированного Page.Master свойства к типу Site , можно ссылаться на свойства и методы, относящиеся к сайту. Как показано на рисунке 7, свойство GridMessageText public отображается в раскрывающемся списке IntelliSense.

IntelliSense показывает общедоступные свойства и методы главной страницы

Рис. 07. IntelliSense показывает общедоступные свойства и методы главной страницы (щелкните, чтобы просмотреть полноразмерное изображение)

Примечание

Если вы назвали файл MasterPage.master master подкачки, имя класса кода программной части страницы master — MasterPage. Это может привести к неоднозначности кода при приведение типа System.Web.UI.MasterPage к классу MasterPage . Короче говоря, необходимо полностью определить тип, к которому выполняется приведение, что может быть немного сложно при использовании модели проекта веб-сайта. Я хотел бы либо убедиться, что при создании страницы master вы назовете ее нечто другоеMasterPage.master, либо, что еще лучше, создать строго типизированную ссылку на страницу master.

Создание ссылки на Strongly-Typed с директивой@MasterType

При внимательном просмотре можно увидеть, что класс кода программной части страницы ASP.NET является разделяемым классом (обратите внимание на partial ключевое слово в определении класса). Разделяемые классы появились в C# и Visual Basic with.NET Framework 2.0 и, в двух словах, позволяют определять члены класса в нескольких файлах. Например, файл AddProduct.aspx.csкласса кода программной части содержит код, который мы, разработчик страницы, создаем. В дополнение к нашему коду подсистема ASP.NET автоматически создает отдельный файл класса со свойствами и обработчиками событий, которые преобразуют декларативную разметку в иерархию классов страницы.

Автоматическое создание кода, которое происходит при каждом посещении ASP.NET страницы, открывает путь для некоторых довольно интересных и полезных возможностей. В случае master страниц, если мы сообщаем подсистеме ASP.NET, какая страница master используется нашей страницей содержимого, она создает строго типизированное Master свойство для нас.

Используйте директиву ,@MasterType чтобы сообщить обработчику ASP.NET о типе страницы master содержимого. Директива @MasterType может принимать имя типа страницы master или путь к файлу. Чтобы указать, что AddProduct.aspx страница используется Site.master в качестве master страницы, добавьте следующую директиву в начало :AddProduct.aspx

<%@ MasterType VirtualPath="~/Site.master" %>

Эта директива указывает подсистеме ASP.NET добавить строго типизированную ссылку на страницу master с помощью свойства с именем Master. С помощью директивы @MasterType можно вызывать Site.master открытые свойства и методы страницы master непосредственно через Master свойство без каких-либо приведения.

Примечание

Если опустить директиву @MasterType , синтаксис Page.Master и возврат одного и Master того же: слабо типизированного объекта на страницу master страницы. Если включить директиву @MasterType , то Master возвращает строго типизированную ссылку на указанную master страницу. Page.MasterОднако по-прежнему возвращает слабо типизированные ссылки. Более подробные сведения о том, почему это так и как Master создается свойство при @MasterType включении директивы, см. в записи @MasterTypeблога К. Скотта Аллена в ASP.NET 2.0.

Обновление главной страницы после добавления нового продукта

Теперь, когда мы знаем, как вызывать открытые свойства и методы страницы master со страницы содержимого, мы готовы обновить AddProduct.aspx страницу, чтобы страница master обновлялась после добавления нового продукта. В начале шага 4 мы создали обработчик событий для события элемента управления ItemInserting DetailsView, который выполняется сразу после добавления нового продукта в базу данных. Добавьте следующий код в этот обработчик событий:

protected void NewProduct_ItemInserted(object sender, DetailsViewInsertedEventArgs e) 
{ 
    // Cast the loosely-typed Page.Master property and then set the GridMessageText property 
    Site myMasterPage = Page.Master as Site; 
    myMasterPage.GridMessageText = string.Format("{0} added to grid...", e.Values["ProductName"]); 
    // Use the strongly-typed Master property 
    Master.RefreshRecentProductsGrid();
}

В приведенном выше коде используется как слабо типизированное Page.Master свойство, так и строго типизированное Master свойство. Обратите внимание, что GridMessageText свойство имеет значение "ProductName добавлено в сетку..." Только что добавленные значения продукта доступны через коллекцию e.Values . Как видите, доступ к только что добавленным ProductName значениям осуществляется через e.Values["ProductName"].

На рисунке 8 показана AddProduct.aspx страница сразу после добавления в базу данных нового продукта — Scott's Soda. Обратите внимание, что только что добавленное название продукта указано в метке страницы master и что GridView обновлен, чтобы включить продукт и его цену.

Метка главной страницы и GridView Отображение Just-Added продукта

Рис. 08. Метка главной страницы и GridView Отображение продукта Just-Added (щелкните для просмотра полноразмерного изображения)

Сводка

В идеале страница master и страницы ее содержимого полностью отделены друг от друга и не требуют никакого уровня взаимодействия. Хотя master страницы и страницы содержимого должны разрабатываться с учетом этой цели, существует ряд распространенных сценариев, в которых страница содержимого должна быть связана со своей master страницей. Одна из наиболее распространенных причин сосредоточена на обновлении определенной части страницы master на основе некоторых действий, которые возникли на странице содержимого.

Хорошей новостью является то, что страница содержимого программно взаимодействует со своей master страницей. Начните с создания открытых свойств или методов на странице master, которые инкапсулируют функциональные возможности, которые должны вызываться страницей содержимого. Затем на странице содержимого получите доступ к свойствам и методам страницы master через слабо типизированное Page.Master свойство или используйте директиву @MasterType , чтобы создать строго типизированную ссылку на страницу master.

В следующем руководстве мы рассмотрим, как master страницы программно взаимодействовать с одной из страниц содержимого.

Счастливое программирование!

Дополнительные материалы

Дополнительные сведения о темах, рассмотренных в этом руководстве, см. в следующих ресурсах:

Об авторе

Скотт Митчелл(Scott Mitchell), автор нескольких книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с веб-технологиями Майкрософт с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Sams Teach Yourself ASP.NET 3,5 в 24 часа. Скотт может быть доступен в mitchell@4GuysFromRolla.com или через его блог по адресу http://ScottOnWriting.NET.

Особая благодарность

Эта серия учебников была рассмотрена многими полезными рецензентами. Ведущим рецензентом этого руководства был Зак Джонс. Хотите просмотреть предстоящие статьи MSDN? Если да, бросить мне строку на mitchell@4GuysFromRolla.com