Опубликован: 07.05.2010 | Доступ: свободный | Студентов: 1676 / 62 | Оценка: 4.56 / 4.06 | Длительность: 34:11:00
Лекция 3:

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>

Представление этого кода разметки в окне броузера имеет такой вид

Представление страницы ControlTree.aspx в окне броузера

Представление страницы ControlTree.aspx в окне броузера
  • Установите для кнопки 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-страницы в зависимости от содержимого запроса пользователя.