Web-формы
Страница как контейнер элементов управления
При вызове Web-формы (страницы) она загружается в память сервера и создается как объект с инициализацией своих свойств и срабатыванием событий. Затем форма запрашивает генерацию кода у всех элементов управления страницы. Каждый из этих элементов управления в свою очередь может содержать дочерние элементы управления и каждый из них тоже отвечает за генерацию собственного кода. По мере генерации этих элементов управления форма собирает полученный HTML-код в завершенную страницу.
Каждый раз, когда страница создается в ответ на HTTP-запрос, система ASP.NET инспектирует файл .aspx. Для каждого найденного дескриптора элемента управления она создает и настраивает объект элемента управления, а затем добавляет этот объект к странице как ее дочерний элемент управления. Ссылки на все дочерние элементы страницы размещаются в коллекции Page.Controls.
Пример отображения дерева элементов управления
Приведем пример поиска и вывода типа и имен элементов управления страницы. Найденную информацию будем размещать последовательно в конец формируемой HTML-страницы. Чтобы перебрать все дочерние элементы управления страницы на необходимую глубину, будем использовать рекурсивный вызов функции. Элементы управления сгруппируем как дочерние в серверном элементе Panel.
- Добавьте к проекту новую страницу с именем ControlTree.aspx с раздельным кодом в файле ControlTree.aspx.cs.
- Пометьте ее как стартовую
- Поместите на страницу элемент управления Panel из вкладки Standard панели Toolbox
- Поместите на панель три кнопки Button, одну метку Label и текстовое поле TextBox
- Разместите за пределами панели, но внутри дескриптора <form>, внизу еще одну кнопку Button
- Введите сверху и снизу за пределами дескриптора <form> статический HTML-текст внутри дескрипторов параграфа <p></p>
Код разметки для полученной страницы должен выглядеть примерно так
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ControlTree.aspx.cs" Inherits="ControlTree" %> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Дерево элементов управления</title> </head> <body> <p> <i>Это статический текст 1</i></p> <form id="Controls" method="post" runat="server"> <div> <asp:Panel ID="MainPanel" runat="server" Height="121px" Width="267px"> <asp:Button ID="Button1" runat="server" Text="Button1" /> <asp:Button ID="Button2" runat="server" Text="Button2" /> <asp:Button ID="Button3" runat="server" Text="Button3" /> <p /> <asp:Label ID="Label1" runat="server" Text="Label">Name:</asp:Label> <asp:TextBox ID="TextBox1" runat="server" Width="195px"></asp:TextBox> </asp:Panel> <asp:Button ID="Button4" runat="server" Text="Button4" /> </div> </form> <p> <i>Это статический текст 2</i></p> </body> </html>
Представление этого кода разметки в окне броузера имеет такой вид
- Установите для кнопки Button4 свойство ToolTip (всплывающая подсказка) в состояние Сканировать все
- Создайте обработчик кнопки Button4
-
Заполните кодовый файл так
using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; public partial class ControlTree : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { // Начало сканирования всех нелитеральных элементов управления DisplayControl(Page.Controls, 0, false); // Горизонтальная линия по окончании вывода Response.Write("<hr />"); } protected void Button4_Click(object sender, EventArgs e) { // Начало сканирования всех литеральных элементов управления DisplayControl(Page.Controls, 0, true); // Горизонтальная линия по окончании вывода Response.Write("<hr />"); } private void DisplayControl(ControlCollection controls, int depth, bool literalFlag) { foreach (Control control in controls) { // Выявлять литеральные (статические) элементы управления bool literalControl = control is LiteralControl; // Отобразить элемент управления if (literalControl == literalFlag) { // Использовать параметр depth для определения // отступов в выводе дерева элементов управления Response.Write(new String('-', depth * 4) + "-->"); String literalText = ""; if (literalControl) literalText = "text" + ((LiteralControl)control).Text; Response.Write(control.GetType().ToString() + " - <b>" + control.ID + literalText + "</b><br />"); } // Проверять дочерние элементы управления рекурсивно if (control.Controls != null) { DisplayControl(control.Controls, depth + 1, literalFlag); } } } }
-
Запустите страницу. После щелчка на кнопке Button4 должен получиться примерно такой HTML-выход
-->System.Web.UI.HtmlControls.HtmlHead - ------>System.Web.UI.HtmlControls.HtmlTitle - -->System.Web.UI.HtmlControls.HtmlForm - Controls ------>System.Web.UI.WebControls.Panel - MainPanel ---------->System.Web.UI.WebControls.Button - Button1 ---------->System.Web.UI.WebControls.Button - Button2 ---------->System.Web.UI.WebControls.Button - Button3 ---------->System.Web.UI.WebControls.Label - Label1 ---------->System.Web.UI.WebControls.TextBox - TextBox1 ------>System.Web.UI.WebControls.Button - Button4 -->System.Web.UI.LiteralControl - text -->System.Web.UI.LiteralControl - text Это статический текст 1 ------>System.Web.UI.LiteralControl - text ---------->System.Web.UI.LiteralControl - text ---------->System.Web.UI.LiteralControl - text ---------->System.Web.UI.LiteralControl - text ---------->System.Web.UI.LiteralControl - text ---------->System.Web.UI.LiteralControl - text ---------->System.Web.UI.LiteralControl - text ------>System.Web.UI.LiteralControl - text ------>System.Web.UI.LiteralControl - text -->System.Web.UI.LiteralControl - text Это статический текст 2
Объекты LiteralControl, которые мы определяли в нашем коде и отдельно распечатывали по кнопке Button4, предоставляют немногое в отношении функциональности. Например, мы не можем программно устанавливать информацию, связанную со стилями, наподобие цвета или шрифта. У них также нет уникальных серверных идентификаторов. Однако мы можем манипулировать содержимым LiteralControl с использованием его свойства Text, что и продемонстрировано в последнем примере.
Здесь при рекурсивном обходе дерева элементов управления мы учитывали тот факт, что ASP.NET генерирует страницу иерархически. Она генерирует непосредственно только верхний уровень элементов управления, т.е. только свойство-контейнер ( коллекцию элементов управления ) Controls самой страницы. Если какой-то элемент управления содержит дочерние элементы, т.е. сам является контейнером, то он имеет свое собственное свойство-контейнер Controls.
Обратите внимание, что задав свойство ToolTip конопки Button4, мы организовали для пользователя появление всплывающей подсказки при наведении курсора мыши на кнопку. Фактически серверный элемент Button4 сгенерировал в своем HTML-выводе атрибут title="Сканировать все".
Программное управление заголовком страницы
Ранее мы говорили, что чтобы сделать дескриптор HTML элементом управления, необходимо добавить в него атрибут runat="server". Но в сканированном выводе последнего примера система ASP.NET нашла элемент управления заголовком страницы
System.Web.UI.HtmlControls.HtmlHead
Visual Studio 2005 автоматически считает дескриптор <head> серверным элементом. Значит мы можем управлять им программно. Объект HtmlHead наследует предопределенный интерфейс IPageHeader и содержит следующие свойства:
- Title - название HTML-страницы, которое отображается в заголовке броузера
- LinkedStyleSheets - коллекция объектов для настройки стилей всего документа через внешнюю таблицу стилей
- StyleSheet - настройка встраиваемых стилей
- Metadata - коллекция объектов для настройки дескрипторов метаданных
Пример:
Page.Header.Title = "Это программно заданный заголовок"; Page.Header.Metadata.Add("Keywords", "Рыжик, Пыжик, ГдеТыБыл"); Page.Header.Metadate.Add(Description", "Русские народные мелодии");
Элемент управления HtmlHead полезен на сверхдинамических страницах, когда может возникнуть потребность в изменении ключевых слов и названия HTML-страницы в зависимости от содержимого запроса пользователя.