Поделиться через


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

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

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

Введение

В предыдущем руководстве было рассмотрено, как программно взаимодействовать страницы содержимого со своей master страницей. Напомним, что мы обновили страницу master, добавив элемент управления GridView со списком пяти последних добавленных продуктов. Затем мы создали страницу содержимого, с которой пользователь может добавить новый продукт. При добавлении нового продукта страница содержимого должна была указать странице master обновить gridView, чтобы она включала только что добавленный продукт. Эта функция была реализована путем добавления открытого метода на страницу master, которая обновила данные, привязанные к GridView, а затем вызвала этот метод со страницы содержимого.

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

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

Подстрекательство программного взаимодействия с помощью событий и обработчиков событий

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

Рассмотрим веб-элемент управления ASP.NET, например элемент управления Кнопка. Элемент управления Кнопка может отображаться на любом количестве ASP.NET страниц и нуждается в механизме, с помощью которого он может оповещать страницу о том, что она была нажата. Это достигается с помощью событий. В частности, элемент управления Button вызывает событие Click при щелчке; страница ASP.NET, содержащая Кнопку, может при необходимости реагировать на это уведомление с помощью обработчика событий.

Этот же шаблон можно использовать для использования функции триггера страницы master на страницах содержимого:

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

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

Шаг 1. Отображение продуктов на странице содержимого

Первым делом мы создадим страницу содержимого со списком продуктов из базы данных Northwind. (Мы добавили базу данных Northwind в проект в предыдущем руководстве Взаимодействие с главной страницей из страницы содержимого.) Начните с добавления новой страницы ASP.NET в ~/Admin папку с именем Products.aspx, обязательно привязав ее к Site.master странице master. На рисунке 1 показана Обозреватель решений после добавления этой страницы на веб-сайт.

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

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

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

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

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

Добавление этого <siteMapNode> элемента отражено в списке "Уроки" (см. рис. 5).

Вернитесь к Products.aspx. В элементе управления Содержимое для MainContentдобавьте элемент управления GridView и назовите его ProductsGrid. Привяжите GridView к новому элементу управления SqlDataSource с именем ProductsDataSource.

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

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

Настройте мастер таким образом, чтобы он использовал базу данных Northwind. Если вы работали с предыдущим руководством, у вас уже должна быть строка подключения с именем NorthwindConnectionString в Web.config. Выберите этот строка подключения из раскрывающегося списка, как показано на рисунке 3.

Настройка SqlDataSource для использования базы данных Northwind

Рис. 03. Настройка SqlDataSource для использования базы данных Northwind (щелкните для просмотра полноразмерного изображения)

Затем укажите оператор элемента управления SELECT источником данных, выбрав таблицу Products в раскрывающемся списке ProductName и возвратив столбцы и UnitPrice (см. рис. 4). Нажмите кнопку Далее, а затем — Готово, чтобы завершить работу мастера настройки источника данных.

Возврат полей ProductName и UnitPrice из таблицы Products

Рис. 04. Возврат ProductName полей и UnitPrice из Products таблицы (щелкните для просмотра полноразмерного изображения)

Вот и все! После завершения работы мастера Visual Studio добавляет два Поля BoundField в GridView для зеркало двух полей, возвращаемых элементом управления SqlDataSource. Далее приведена разметка элементов управления GridView и SqlDataSource. На рисунке 5 показаны результаты при просмотре в браузере.

<asp:GridView ID="ProductsGrid" runat="server" AutoGenerateColumns="False" 
 DataSourceID="ProductsDataSource">
 <Columns>
 <asp:BoundField DataField="ProductName" HeaderText="ProductName" 
 SortExpression="ProductName" />
 <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" 
 SortExpression="UnitPrice" />
 </Columns>
</asp:GridView>

<asp:SqlDataSource ID="ProductsDataSource" runat="server" 
 ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>" 
 SelectCommand="SELECT [ProductName], [UnitPrice] FROM [Products]">
</asp:SqlDataSource>

Каждый продукт и его цена перечислены в GridView

Рис. 05. Каждый продукт и его цена указаны в GridView (Щелкните для просмотра полноразмерного изображения)

Примечание

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

Шаг 2. Добавление кнопки "Двойные цены" на главную страницу

Следующей задачей является добавление веб-элемента управления "Кнопка" на страницу master, которая при щелчке удвоит цену всех продуктов в базе данных. Откройте страницу Site.master master и перетащите кнопку с панели элементов на Designer, поместив ее под RecentProductsDataSource элементом управления SqlDataSource, добавленным в предыдущем руководстве. Задайте свойству Кнопки ID значение , DoublePrice а свойству Text — значение "Двойные цены на продукты".

Затем добавьте элемент управления SqlDataSource на страницу master, назвав его DoublePricesDataSource. Этот sqlDataSource будет использоваться для выполнения инструкции UPDATE для удвоить все цены. В частности, необходимо задать для его ConnectionString свойств и UpdateCommand соответствующие строка подключения и UPDATE оператору . Затем необходимо вызвать метод этого элемента управления Update SqlDataSource при нажатии кнопки DoublePrice . Чтобы задать ConnectionString свойства и UpdateCommand , выберите элемент управления SqlDataSource и перейдите к окно свойств. Свойство ConnectionString перечисляет строки подключения, которые уже хранятся в Web.config раскрывающемся списке; выберите параметр, как показано на NorthwindConnectionString рисунке 6.

Настройка SqlDataSource для использования NorthwindConnectionString

Рис. 06. Настройка SqlDataSource для использования NorthwindConnectionString (щелкните для просмотра полноразмерного изображения)

Чтобы задать UpdateCommand свойство, найдите параметр UpdateQuery в окно свойств. При выборе этого свойства отображается кнопка с многоточием; Нажмите эту кнопку, чтобы открыть диалоговое окно Редактор команды и параметры, показанное на рисунке 7. В текстовое поле диалогового окна введите следующую UPDATE инструкцию:

UPDATE Products SET UnitPrice = UnitPrice * 2

Этот оператор при выполнении удвоит UnitPrice значение для каждой Products записи в таблице.

Установка свойства UpdateCommand в SqlDataSource

Рис. 07. Установка свойства SqlDataSource UpdateCommand (щелкните для просмотра полноразмерного изображения)

После настройки этих свойств декларативная разметка элементов управления Button и SqlDataSource должна выглядеть примерно так:

<asp:Button ID="DoublePrice" runat="server" 
 Text="Double Product Prices" />

<asp:SqlDataSource ID="DoublePricesDataSource" runat="server" 
 UpdateCommand="UPDATE Products SET UnitPrice = UnitPrice * 2" 
 ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>" 
 ProviderName="<%$ ConnectionStrings:NorthwindConnectionString.ProviderName %>">
</asp:SqlDataSource>

Остается только вызвать его Update метод при нажатии DoublePrice кнопки. Создайте Click обработчик событий для DoublePrice Button и добавьте следующий код:

protected void DoublePrice_Click(object sender, EventArgs e)
{
    // Double the prices
    DoublePricesDataSource.Update();
}

Чтобы протестировать эту функцию, перейдите на страницу ~/Admin/Products.aspx , созданную на шаге 1, и нажмите кнопку "Удвоить цены на продукты". Нажатие кнопки вызывает обратную передачу DoublePrice и выполняет обработчик событий Button Click , удвоив цены на все продукты. Затем страница повторно отрисовывается, а разметка возвращается и снова отображается в браузере. Однако GridView на странице содержимого содержит те же цены, что и до нажатия кнопки "Двойные цены на продукты". Это связано с тем, что данные, изначально загруженные в GridView, хранятся в состоянии представления, поэтому они не перезагружаются при обратной отправке, если не указано иное. Если вы перейдете на другую страницу, а затем вернетесь на нее ~/Admin/Products.aspx , вы увидите обновленные цены.

Шаг 3. Создание события при удволении цен

Поскольку GridView на ~/Admin/Products.aspx странице не сразу отражает удвоение цен, пользователь может понять, что он не нажал кнопку "Двойные цены на продукты" или что она не сработала. Они могут попытаться нажать кнопку еще несколько раз, удвоив цены снова и снова. Чтобы устранить эту проблему, необходимо, чтобы в сетке на странице содержимого отображались новые цены сразу после их удвоение.

Как упоминалось ранее в этом руководстве, необходимо вызывать событие на странице master каждый раз, когда пользователь нажимает кнопкуDoublePrice. Событие — это способ для одного класса (издателя события) уведомить другого о наборе других классов (подписчиках событий) о том, что произошло что-то интересное. В этом примере master страница является издателем события. Страницы содержимого, которые интересуются нажатием DoublePrice кнопки, являются подписчиками.

Класс подписывается на событие путем создания обработчика событий, который является методом, который выполняется в ответ на возникающее событие. Издатель определяет события, которые он вызывает, определяя делегат события. Делегат события указывает, какие входные параметры должен принимать обработчик событий. В платформа .NET Framework делегаты событий не возвращают значения и принимают два входных параметра:

  • , Objectкоторый определяет источник события, и
  • Класс, производный от System.EventArgs

Второй параметр, передаваемый обработчику событий, может содержать дополнительные сведения о событии. Хотя базовый EventArgs класс не передает никаких сведений, платформа .NET Framework включает ряд классов, которые расширяют EventArgs и охватывают дополнительные свойства. Например, CommandEventArgs экземпляр передается обработчикам событий, которые реагируют на Command событие, и включает два информационных свойства: CommandArgument и CommandName.

Примечание

Дополнительные сведения о создании, вызове и обработке событий см. в разделе События и Делегаты и Делегаты событий на простом английском языке.

Чтобы определить событие, используйте следующий синтаксис:

public event eventDelegate eventName;

Так как нам нужно оповещать страницу содержимого, только когда пользователь нажал DoublePrice кнопку и не нужно передавать другие дополнительные сведения, мы можем использовать делегат EventHandlerсобытия , который определяет обработчик событий, который принимает в качестве второго параметра объект типа System.EventArgs. Чтобы создать событие на странице master, добавьте следующую строку кода в класс кода программной части страницы master:

public partial class Site : System.Web.UI.MasterPage
{
    public event EventHandler PricesDoubled;

    ...
}

Приведенный выше код добавляет общедоступное событие на страницу master с именем PricesDoubled. Теперь нам нужно поднять это событие после того, как цены были удвоены. Чтобы вызвать событие, используйте следующий синтаксис:

if (eventName != null)
    eventName(sender, eventArgs);

Где sender и eventArgs — это значения, которые необходимо передать обработчику событий подписчика.

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

protected void DoublePrice_Click(object sender, EventArgs e)
{
    // Double the prices
    DoublePricesDataSource.Update();

    // Refresh RecentProducts
    RecentProducts.DataBind();

    // Raise the PricesDoubled event
    if (PricesDoubled != null)
    PricesDoubled(this, EventArgs.Empty);
}

Как и ранее, Click обработчик событий начинается с вызова DoublePricesDataSource метода элемента управления Update SqlDataSource, чтобы удвоить цены на все продукты. После этого есть два дополнения к обработчику событий. RecentProducts Сначала обновляются данные GridView. Этот элемент GridView был добавлен на страницу master в предыдущем руководстве и отображает пять последних добавленных продуктов. Нам нужно обновить эту сетку, чтобы она отображала только что удвоив цены на эти пять продуктов. После этого PricesDoubled возникает событие . Ссылка на саму страницу master (this) отправляется обработчику событий в качестве источника события, а пустой EventArgs объект отправляется в качестве аргументов события.

Шаг 4. Обработка события на странице содержимого

На этом этапе страница master вызывает событие PricesDoubled при каждом щелчке DoublePrice элемента управления Кнопка. Тем не менее, это только половина битвы - нам по-прежнему нужно обрабатывать событие в подписчике. Это включает два шага: создание обработчика событий и добавление кода подключения событий, чтобы при возникновении события выполнялся обработчик событий.

Начните с создания обработчика событий с именем Master_PricesDoubled. Из-за того, как мы определили PricesDoubled событие на странице master, два входных параметра обработчика событий должны иметь типы Object и EventArgsсоответственно. В обработчике событий вызовите ProductsGrid метод GridView DataBind для повторной привязки данных к сетке.

private void Master_PricesDoubled(object sender, EventArgs e)
{
    // Rebind data to ProductsGrid
    ProductsGrid.DataBind();
}

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

publisher.eventName += new eventDelegate(methodName);

publisher — это ссылка на объект, который предлагает eventName, а methodName — имя обработчика событий, определенного в подписчике, который имеет сигнатуру, соответствующую eventDelegate. Иными словами, если делегатом события является EventHandler, то methodName должно быть именем метода в подписчике, который не возвращает значение и принимает два входных параметра типов Object и EventArgsсоответственно.

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

Откройте ~/Admin/Products.aspx и создайте Page_PreInit обработчик событий:

protected void Page_PreInit(object sender, EventArgs e)
{
    // TODO: Put event wiring logic here
}

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

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

Давайте воспользуемся последним подходом. Добавьте следующую @MasterType директиву в верхнюю часть декларативной разметки страницы:

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

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

protected void Page_PreInit(object sender, EventArgs e)
{
    // Create an event handler for the master page's PricesDoubled event
    Master.PricesDoubled += new EventHandler(Master_PricesDoubled);
}

При использовании этого кода элемент GridView на странице содержимого обновляется при каждом нажатии кнопки DoublePrice .

Это поведение показано на рисунках 8 и 9. На рисунке 8 показана страница при первом посещении. Обратите внимание, что значения price в RecentProducts GridView (в левом столбце страницы master) и ProductsGrid GridView (на странице содержимого). На рис. 9 показан тот же экран сразу после DoublePrice нажатия кнопки. Как видите, новые цены мгновенно отражаются в обоих GridView.

Значения начальной цены

Рис. 08. Начальные значения цен (щелкните, чтобы просмотреть полноразмерное изображение)

Цены Just-Doubled отображаются в GridViews

Рис. 09. Цены Just-Doubled отображаются в GridViews (Щелкните, чтобы просмотреть полноразмерное изображение)

Сводка

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

Хотя программное взаимодействие между содержимым и master страницей может происходить из содержимого или master страницы, используемый шаблон взаимодействия зависит от источника. Различия обусловлены тем, что страница содержимого имеет одну страницу master, но на master странице может быть много разных страниц содержимого. Вместо того чтобы 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