| Китай |
Пользовательские элементы управления
Упражнение 2. Программирование пользовательского элемента
До сих пор мы работали только с интерфейсной частью и не использовали код застраничного файла, хотя и создали его. Но чаще всего это нужно делать, чтобы добавить функциональность, которая может понадобиться клиенту.
Воспользуемся стандартным элементом управления LinkButton, который будет снимать с таймера сервера текущее время и отображать его клиенту. Для разнообразия код C# и дескрипторную разметку поместим в одном файле.
-
Вызовите
мастер для создания пользовательского элемента управления,
выполнив команду Website/Add New Item. Установите шаблон
в значение Web User Control, сбросьте флажок Place
code in separate file и задайте имя файла TimeDisplay.ascx
-
Поместите
на страницу TimeDisplay.ascx в
режиме Design стандартный
элемент управления LinkButton из
вкладки Standard
-
Через
панель Properties измените ID элемента на lnkTime
-
Двойным
щелчком на свободном месте редактора Design создайте
обработчик Page_Load()
-
При
выделенном элементе lnkTime установите панель Properties в
режим Events (кнопка с изображением молнии
вверху панели), найдите событие Click и
двойным щелчком на поле его значения создайте обработчик lnkTime_Click()
-
Заполните
обработчики кодом, чтобы файл стал таким
<%@ Control Language="C#" ClassName="TimeDisplay" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
RefreshTime();
}
protected void lnkTime_Click(object sender, EventArgs e)
{
RefreshTime();
}
public void RefreshTime()
{
lnkTime.Text = DateTime.Now.ToLongTimeString();
}
</script>
<asp:LinkButton ID="lnkTime" runat="server" OnClick="lnkTime_Click" />
Листинг
32.5.
Код файла TimeDisplay.ascx
В коде мы добавили свою функцию RefreshTime(), поскольку ее код нужно вызывать в двух местах. Без этой функции вполне можно обойтись, но мы представили себе, будто ее тело состоит из большого количества строк.
-
Чтобы
протестировать наш код, добавьте к приложению новую страницу
с именем TimeDisplayTest.aspx
-
Переведите
страницу TimeDisplayTest.aspx в
режим Design и перетащите
на нее из панели Solution Explorer файл TimeDisplay.ascx с
пользовательским элементом управления
В результате оболочка добавит к странице пользовательский элемент управления и зарегистрирует его
<%@ Page Language="C#" %>
<%@ Register Src="TimeDisplay.ascx" TagName="TimeDisplay" TagPrefix="uc1" %>
<script runat="server">
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<uc1:TimeDisplay ID="TimeDisplay1" runat="server" />
</div>
</form>
</body>
</html>
Листинг
32.6.
Код страницы TimeDisplayTest.aspx после добавления пользовательскогоэлемента
-
Выполните
страницу, которая на клиенте будет такой
При каждом щелчке пользователя на ссылке-кнопке броузер будет инициировать обратную отсылку на сервер, разработанная страница при исполнении снимет с таймера сервера новое значение времени и сгенерирует броузеру соответствующий HTML-отклик.
Что мы только что сделали в нашем упражнении. Мы код, который можно исполнить одной страницей, разделили на две части, выделив типовую часть в отдельный файл, который назвали пользовательским элементом управления. Это напоминает прием упаковки кода в отдельную функцию. Выполним обратную операцию и сосредоточим весь код на одной исполнимой странице.
-
Добавьте
к проекту страницу TimeDisplay.aspx без
файла отделенного кода и назначьте ее стартовой -
Поместите
на страницу из вкладки Standard библиотечный элемент управления LinkButton и
присвойте ему имя lnkTime
-
Создайте
на странице обработчики как в пользовательском элементе управления TimeDisplay.ascx и
заполните их таким же кодом
<%@ Page Language="C#" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
RefreshTime();
}
protected void lnkTime_Click(object sender, EventArgs e)
{
RefreshTime();
}
public void RefreshTime()
{
lnkTime.Text = DateTime.Now.ToLongTimeString();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:LinkButton ID="lnkTime" runat="server" OnClick="lnkTime_Click" />
</div>
</form>
</body>
</html>
Листинг
32.7.
Код исполнимой страницы TimeDisplay.aspx
-
Выполните
страницу и убедитесь, что выдается точно такой же результат,
как и в случае с промежуточным файлом TimeDisplay.ascx,
в котором находится элемент LinkButton и все обработчики
Добавление свойства
Расширим возможности нашего пользовательского элемента управления и добавим в код общедоступное свойство Format, которому будем передавать либо пустую строку, либо строку форматирования. В зависимости от этого пользовательский элемент управления будет способен отображать текущее время на кнопке LinkButton в разных форматах.
-
Измените
код файла TimeDisplay.ascx следующим образом
<%@ Control Language="C#" ClassName="TimeDisplay" %>
<script runat="server">
private string format; // Контролируемое свойством поле
public string Format // Определение свойства Format
{
get { return format; }
set { format = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
RefreshTime();
}
protected void lnkTime_Click(object sender, EventArgs e)
{
RefreshTime();
}
// Значение format задаем в исполнимой странице через атрибут Format
public void RefreshTime()
{
if (format == "")
lnkTime.Text = DateTime.Now.ToLongTimeString();
else
lnkTime.Text = DateTime.Now.ToString(format);
}
</script>
<asp:LinkButton ID="lnkTime" runat="server" OnClick="lnkTime_Click" />
Листинг
32.8.
Улучшенный код файла TimeDisplay.ascx
-
Измените
код тестовой страницы TimeDisplayTest.aspx следующим
образом
<%@ Page Language="C#" %>
<%@ Register Src="TimeDisplay.ascx" TagName="TimeDisplay" TagPrefix="uc1" %>
<script runat="server">
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<uc1:TimeDisplay ID="TimeDisplay1" runat="server" Format="" />
<br />
<br />
<hr />
<br />
<uc1:TimeDisplay ID="TimeDisplay2" runat="server"
Format="Сегодня dddd, dd MMMM yyyy<br />Текущее время HH:mm:ss" />
</div>
</form>
</body>
</html>
Листинг
32.9.
Код тестовой страницы TimeDisplayTest.aspx
Тестовая страница является клиентом пользовательского элемента управления. Именно в дескрипторе элемента на клиенте мы определяем значение добавленного свойства Format как атрибут этого дескриптора. Обратите внимание, что в подсказчике кода IntelliSense, применяемом при редактировании дескриптора пользовательского элемента управления, появилось новое свойство Format.
Представление тестовой страницы с пользовательским элементом управления на броузере клиента будет выглядеть так
Здесь создаются два экземпляра элемента управления TimeDisplay, первый из которых отображает дату в формате по умолчанию, а другой - в заданном формате.
Порядок генерации событий инициализации
При создании пользовательских элементов управления и добавления в них своих свойств важно знать, в каком порядке происходит создание и инициализация объектов на странице, использующей пользовательский элемент управления. Этот порядок следующий:
- Производится удаленный запрос исполнимой страницы и она загружается в память сервера
- Исполнимая страница инициирует загрузку в память пользовательского элемента управления
- Выполняется настройка пользовательского элемента управления присваиванием значений атрибутов, предусмотренных в дескрипторе описания
- Создается объект родительской страницы с уже готовым объектом пользовательского элемента с начальными настройками, определенными свойствами по умолчанию и значениями атрибутов в дескрипторном описании
- Выполняется событие Page.Load родительской страницы, в обработчике Page_Load() которого можно предусмотреть переназначение атрибутов-свойств пользовательского элемента управления
- Выполняется событие Page.Load пользовательского элемента управления
Если мы будем инициализировать пользовательский элемент управления в его обработчике Page_Load(), то он перезапишет все свои настройки, выполненные в родительском коде, поскольку срабатывает последним. Так, если бы в последнем примере обработчик Page_Load() пользовательского элемента управления инициализировал поле format и имел бы вид
protected void Page_Load(object sender, EventArgs e)
{
format = "";
if (!Page.IsPostBack)
RefreshTime();
}то мы бы всегда получали результат варианта без форматирования, а именно




