Программирование на ASP.NET

Серверные элементы управления

Показывать лекцию целиком
Файлы к лекции Вы можете скачать здесь.

Рассмотрим некоторые серверные элементы управления, которые находятся в пространстве имен System.Web.UI.WebControls библиотечной сборки C:\WINNT\Microsoft.NET\Framework\v2.0.50727\System.Web.dll. Все они представляют собой некоторую абстракцию, способную генерировать клиентский код (HTML и JavaScript). Некоторые из этих элементов отображаются на странице в режиме Design примерно так, как они будут представлены пользователю, а некоторые просто визуализируются объектом, который при выполнении сгенерирует нужный клиентский код в соответствии с его настройками. При этом неважно, будут ли эти элементы созданы и настроены в режиме проектирования, или в режиме выполнения кодовой части страницы, написанной на C#. В режиме проектирования удобнее задавать начальные настройки серверных элементов, а в режиме выполнения управлять элементами с помощью кода в зависимости от действий пользователя, полученных сервером с обратной отсылкой PostBack.

Web-элемент управления Literal

Элемент управления System.Web.UI.WebControls.Literal обладает слабой функциональностью. Он генерирует тег <span> и упаковывает в него текст, присвоенный свойству Text. Это значит, что к выводимому содержимому нельзя применить никакие стили - оно выводится как есть. Но элемент Literal имеет свойство Mode, позволяющее устанавливать способ предварительной обработки выводимого текста с помощью присвоения значений из перечисления System.Web.UI.WebControls.LiteralMode

Перечисление LiteralMode для свойства Mode элемента управления Literal
Mode Значение Text
Transform = 0 Удаляет из текста неподдерживаемые броузером теги. Если теги относятся к языку разметки HTML или XHTML, то содержимое текста не модифицируется
PassThrough = 1 Содержимое свойства Text передается броузеру без изменений
Encode = 2 Управляющие символы кодируются в HTML

Пример

  • Командой меню
  • Переименуйте в панели Solution Explorer созданную по умолчанию страницу Default.aspx в MyLiteral.aspx и удалите из проекта папку App_Data
  • Измените в начале страницы Literal.aspx в директиве @ Page значение параметра Inherits="_Default" на Inherits="MyLiteral"
  • Откройте файл MyLiteral.aspx.cs и измените имя класса страницы с _Default на MyLiteral
  • Отредактируйте обработчик Page_Load следующим образом
    (рис ) Класс изучения режимов элемента Literalusing System;
    using System.Data;
    using System.Configuration;
    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 MyLiteral : System.Web.UI.Page 
    {
        // Свойство для генерации тега <br></br>
        protected HtmlGenericControl BR
        {
            get { return new HtmlGenericControl("br"); }
        }
        
        protected void Page_Load(object sender, EventArgs e)
        {
            Literal literal = new Literal();
            form1.Controls.Add(literal);
            form1.Controls.Add(BR);
            literal.Mode = LiteralMode.Transform;
            literal.Text = @"Transform: <font size=6>Привет студентам СФУ!</font>"
                + @"<script>alert(' Привет студентам кафедры ""ПМ и АСУ"" ')</script>";
        
            literal = new Literal();
            form1.Controls.Add(literal);
            form1.Controls.Add(BR);
            literal.Mode = LiteralMode.PassThrough;
            literal.Text = @"PassThrough: <font size=6>Привет доцентам СФУ!</font>"
                + @"<script>alert(' Привет доцентам кафедры ""ПМ и АСУ"" ')</script>";
        
            literal = new Literal();
            form1.Controls.Add(literal);
            literal.Mode = LiteralMode.Encode;
            literal.Text = @"Encode: <font size=6>Привет ректору СФУ!</font>"
                + @"<script>alert(' Привет заведующему кафедрой ""ПМ и АСУ"" ')</script>";
        }
    }
  • Хотя в разметочной части страницы мы код не создавали, все равно рендеринг страницы будет следующим

    В коде используется функция alert() клиентского языка JavaScript, которая генерирует окно сообщений в броузере. Для простоты, чтобы не запутаться в двойных кавычках, аргумент этой функции заключен в одинарные кавычки. Двойные кавычки в литеральной строке @"..." заэкранированы также двойными кавычками, как этого требует синтаксис языка C#.

    Последняя строка в коде HTML выглядит так

    Encode: lt;font size=6gt;Привет ректору СФУ!lt;/fontgt;lt;scriptgt;alert(' Привет заведующему кафедрой quot;ПМ и АСУquot; ')
    lt;/scriptgt;

    В ней левая угловая скобка заменена на lt;, правая на gt;, а двойные кавычки на quot;. Такой код для броузера будет безопасным, поскольку не даст выполниться вредоносным скриптам злоумышленников, если код поступает от сомнительных источников.

    Web-элементы управления Table, TableRow, TableCell

    Для позиционирования статических данных, рисунков и элементов управления применяются HTML-дескрипторы (теги) <table>. Их можно создать с помощью элемента управления HtmlTable, добавив в дескриптор атрибут runat="server". Но для программного формирования таблиц "на лету" и заполнения их данными удобно использовать более развитые серверные элементы управления Table, TableRow и TableCell, с которыми мы сейчас и познакомимся. Хотя их можно применять и для отображения статических данных.

    Элементы управления Table, TableRow и TableCell не сохраняют состояние после возврата формы на сервер и их нужно восстанавливать заново программным способом, повторно выбирая данные из источника. Альтернативным путем для сохранения состояния строк и ячеек является применение элементов управления DataList и GridView.

    У элемента Table имеется свойство Rows, которое представляет собой коллекцию объектов TableRow. Количество объектов в коллекции равно количеству строк таблицы при рендеринге. В свою очередь, каждый объект TableRow имеет коллекцию ячеек таблицы в виде объектов TableCell, которые в динамическом режиме заполняются данными через свойство TableCell.Text.

    Приведем пример.

  • Добавьте к текущему проекту командой
  • Измените в файле MyTable.aspx.cs класс MyTable следующим образом
    (рис ) Класс динамического формирования таблицы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 MyTable : System.Web.UI.Page
    {
        const int rowMax = 5, colMax = 4;// Размеры таблицы
        // id=form1 форма-родитель в разметочной части страницы
        
        protected void Page_Load(object sender, EventArgs e)
        {
            // Формируем оглавление страницы в HTML
            Label label = new Label();
            form1.Controls.Add(label);
            label.Text = "<h1>Динамическая таблица</h1>";
            label.ForeColor = System.Drawing.Color.Red;
        
            // Формируем саму таблицу
            System.Web.UI.WebControls.Table table =
                new System.Web.UI.WebControls.Table();// Создали таблицу
            form1.Controls.Add(table);// Добавили в форму
        
            // Настраиваем таблицу 
            table.BorderWidth = 1;// Рамка таблицы
            table.Style.Value = "align=center";
            // Формируем строки
            for (int row = 0; row < rowMax; row++)
            {
                TableRow tr = new TableRow();// Создали строку
                table.Rows.Add(tr);// Добавили в таблицу
        
                // Продолжаем настраивать, добавляя ячейки
                for (int col = 0; col < colMax; col++)
                {
                    TableCell tc = new TableCell();// Создали ячейку
                    tr.Cells.Add(tc);// Добавили в строку
        
                    // Настраиваем ячейку
                    tc.Text = string.Format("ячейка{{{0},{1}}}",
                        row + 1, col + 1);
                    tc.BorderWidth = 1;// Рамка ячейки
                    if (row % 2 == 0)// Нечетные строки
                        tc.BackColor = System.Drawing.Color.Moccasin;
                    else // Четные строки
                        tc.BackColor = System.Drawing.Color.PowderBlue;
                }
            }
        
            // Горизонтальная черта
            form1.Controls.Add(new HtmlGenericControl("hr"));
        
            // Подвал страницы
            label = new Label();
            form1.Controls.Add(label);
            label.Text = "<strong>Это подвал страницы (цокольный этаж !)</strong>";
        }
    }
  • Рендеринг этой страницы будет следующим

    Попутно, для справки, напомним цвета, используемые в Web:

    Color Color Name RGB Value Color Color Name RGB Value Color Color Name RGB Value Color Color Name RGB Value
    LightPink #FFB6C1 LightSlateGray #778899 Lime #00FF00 Bisque #FFE4C4
    Pink #FFC0CB SlateGray #708090 ForestGreen #228B22 DarkOrange #FF8C00
    Crimson #DC143C DodgerBlue #1E90FF Green #008000 Linen #FAF0E6
    LavenderBlush #FFF0F5 AliceBlue #F0F8FF DarkGreen #006400 Peru #CD853F
    PaleVioletRed #DB7093 SteelBlue #4682B4 Chartreuse #7FFF00 PeachPuff #FFDAB9
    HotPink #FF69B4 LightSkyBlue #87CEFA LawnGreen #7CFC00 SandyBrown #F4A460
    DeepPink #FF1493 SkyBlue #87CEEB GreenYellow #ADFF2F Chocolate #D2691E
    MediumVioletRed #C71585 DeepSkyBlue #00BFFF DarkOliveGreen #556B2F SaddleBrown #8B4513
    Orchid #DA70D6 LightBlue #ADD8E6 YellowGreen #9ACD32 Seashell #FFF5EE
    Thistle #D8BFD8 PowderBlue #B0E0E6 OliveDrab #6B8E23 Sienna #A0522D
    Plum #DDA0DD CadetBlue #5F9EA0 Beige #F5F5DC LightSalmon #FFA07A
    Violet #EE82EE Azure #F0FFFF LightGoldenrodYellow #FAFAD2 LightSalmon #FFA07A
    Magenta #FF00FF LightCyan #E0FFFF Ivory #FFFFF0 OrangeRed #FF4500
    Fuchsia #FF00FF PaleTurquoise #AFEEEE LightYellow #FFFFE0 DarkSalmon #E9967A
    DarkMagenta #8B008B Cyan #00FFFF Yellow #FFFF00 Tomato #FF6347
    Purple #800080 Aqua #00FFFF Olive #808000 MistyRose #FFE4E1
    MediumOrchid #BA55D3 DarkTurquoise #00CED1 DarkKhaki #BDB76B Salmon #FA8072
    DarkViolet #9400D3 DarkSlateGray #2F4F4F LemonChiffon #FFFACD Snow #FFFAFA
    DarkOrchid #9932CC DarkCyan #008B8B PaleGoldenrod #EEE8AA LightCoral #F08080
    Indigo #4B0082 Teal #008080 Khaki #F0E68C RosyBrown #BC8F8F
    BlueViolet #8A2BE2 MediumTurquoise #48D1CC Gold #FFD700 IndianRed #CD5C5C
    MediumPurple #9370DB LightSeaGreen #20B2AA Cornsilk #FFF8DC Red #FF0000
    MediumSlateBlue #7B68EE Turquoise #40E0D0 Goldenrod #DAA520 Brown #A52A2A
    SlateBlue #6A5ACD Aquamarine #7FFFD4 DarkGoldenrod #B8860B FireBrick #B22222
    DarkSlateBlue #483D8B MediumAquamarine #66CDAA FloralWhite #FFFAF0 DarkRed #8B0000
    Lavender #E6E6FA MediumSpringGreen #00FA9A OldLace #FDF5E6 Maroon #800000
    GhostWhite #F8F8FF MintCream #F5FFFA Wheat #F5DEB3 White #FFFFFF
    Blue #0000FF SpringGreen #00FF7F Moccasin #FFE4B5 WhiteSmoke #F5F5F5
    MediumBlue #0000CD MediumSeaGreen #3CB371 Orange #FFA500 Gainsboro #DCDCDC
    MidnightBlue #191970 SeaGreen #2E8B57 PapayaWhip #FFEFD5 LightGrey #D3D3D3
    DarkBlue #00008B Honeydew #F0FFF0 BlanchedAlmond #FFEBCD Silver #C0C0C0
    Navy #000080 LightGreen #90EE90 NavajoWhite #FFDEAD DarkGray #A9A9A9
    RoyalBlue #4169E1 PaleGreen #98FB98 AntiqueWhite #FAEBD7 Gray #808080
    CornflowerBlue #6495ED DarkSeaGreen #8FBC8F Tan #D2B48C DimGray #696969
    LightSteelBlue #B0C4DE LimeGreen #32CD32 BurlyWood #DEB887 Black #000000

    Web-элемент управления Image

    Элемент управления System.Web.UI.WebControls.Image является упаковкой для размещения рисунка на странице. При рендеринге он генерирует HTML-тег <img> с параметрами, установленными свойствами элемента. Свойство Image.ImageUrl задает путь к изображению, которое хранится на сервере и которое затем броузер запросит при получении тега <img src="ImageUrl" />, сгенерированного элементом Image. Свойство Image.AlternateText генерирует атрибут alt всплывающей подсказки или текст на месте неудачно загруженного рисунка. Эту же функцию выполняет булево свойство Image.GenerateEmptyAlternateText, которое включает генерацию атрибута alt в том случае, если изображение будет пустым.

    Элемент Image не распознает событие Click, для этого служат элементы ImageButton и ImageMap. К тому же последние отслеживают координаты точки курсора относительно изображения, на которую пришелся щелчок мыши.

    Свойство Image.ImageAlign ждет одно из значений одноименного перечисления System.Web.UI.WebControls.ImageAlign, с помощью которого задается режим выравнивания изображения относительно других объектов рендеринга страницы.

    Свойство Image.DescriptionUrl позволяет привязать к изображению страницу, где находятся сведения об изображении в текстовом или звуковом представлении. Используется в случае, если страница готовится для людей со слабым зрением.

    Приведем пример.

  • Добавьте к текущему проекту командой
  • В панели Solution Explorer выделите страницу MyImage.aspx и выполните команду меню Website/Set As Start Page, чтобы сделать страницу стартовой
  • Для корневого узла проекта в панели Solution Explorer вызовите контекстное меню и командой New Folder добавьте каталог Images
  • В панели Solution Explorer выделите папку Images и командой Website/Add Existing Item добавьте к проекту два рисунка из нашего каталога Pictures (или из любого другого источника), например, DOGBIG.png и DOGPLANE.png
  • Измените в файле MyImage.aspx.cs класс MyImage следующим образом
    (рис ) Класс MyImageusing 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 MyImage : System.Web.UI.Page
    {
        Image image;
        
        protected void Page_Load(object sender, EventArgs e)
        {
            //Response.ClearContent();
        
            //Расфасовываем элементы для отклика
            if (!Page.IsPostBack)// Первый запрос
            {
                image = new Image();
                image.ImageUrl = "~/Images/DOGBIG.png";
                image.AlternateText = "Отклик сервера на первый запрос";
                form1.Controls.Add(image);
                image.EnableViewState = false;
            }
            else // Обратная отсылка
            {
                image = new Image();
                image.ImageUrl = "~/Images/DOGPLANE.png";
                image.AlternateText = "Отклик сервера на обратную отсылку";
                form1.Controls.Add(image);
                image.EnableViewState = false;
            }
        
            form1.Controls.Add(new HtmlGenericControl("br"));
        
            Button submit = new Button();
            submit.Text = "PostBack";
            form1.Controls.Add(submit);
            submit.ToolTip = "Это кнопка Submit";
        }
    }
  • Обратите внимание, что значек " ~ " (тильда) в значении свойства ImageUrl означает корневой каталог приложения (но не сайта root ).

    Рендеринг этой страницы при первом запросе будет следующим:

    Web-элемент управления ImageButton

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

    Приведем пример.

  • Добавьте, как и ранее, к текущему проекту страницу с именем MyImageButton.aspx с отделенным кодом. Сделайте ее стартовой и заполните класс MyImageButton следующим кодом
  • 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 MyImageButton : System.Web.UI.Page
    {
        ImageButton imageButton;
        
        protected void Page_Load(object sender, EventArgs e)
        {
            imageButton = new ImageButton();
            form1.Controls.Add(imageButton);
            imageButton.ImageUrl = "~/Images/DOGBIG.png";
            imageButton.AlternateText = "Это рисунок-кнопка";
            imageButton.Click += new ImageClickEventHandler(imageButton_Click);
        
            // Настройка рамки рисунка
            imageButton.BorderWidth = 7;
            imageButton.BorderColor = System.Drawing.Color.Red;
            imageButton.BorderStyle = BorderStyle.Double;
        }
        
        void imageButton_Click(object sender, ImageClickEventArgs e)
        {
            imageButton.AlternateText = String.Format(
                "Координаты щелчка: ({0},{1})", e.X, e.Y);
        }
    }

    Рендеринг этой страницы при очередном щелчке на рисунке будет следующим:

    Обратите внимание на способ настройки рамки рисунка.

    Web-элемент управления ImageMap

    В HTML существует понятие карты изображений (image map), когда один и тот же рисунок, отображаемый в броузере, делится на отдельные чувствительные к щелчкам мыши зоны ( hot spots - горячие пятна). При щелчке пользователя на одной из этих горячих зон броузер инициирует обратную отсылку с закрепленным за зоной URL. Таким образом, из одного рисунка мы можем сделать несколько Submit -кнопок. Карту изображений иногда называют навигационной панелью (Navigation Bar)

    Вот пример рисунка, размеченного условно на отдельные прямоугольные области.

    Давайте вначале рассмотрим применение карты изображений в статическом варианте страниц сайта.

  • Добавьте к корневому узлу проекта статическую страницу с именем
  • Добавьте в папку Images проекта рисунок ImageMap.png (из прилагаемого каталога Pictures )
  • Заполните страницу ImageMap.htm следующим кодом
    (рис ) HTML-код статической страницы ImageMap.htm<html xmlns="http://www.w3.org/1999/xhtml" >
    <head>
        <title>Untitled Page</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <!-- Описание навигационной панели -->
                <map id="NavBar" name="NavBar">
                    <area alt="Один" coords="0, 0, 162, 94" href="one.htm" shape="rect" />
                    <area alt="Два" coords="162, 0, 324, 94" href="two.htm" shape="rect" />
                    <area alt="Три" coords="0, 94, 162, 188" href="three.htm" shape="rect" />
                    <area alt="Четыре" coords="162, 94, 321, 188" href="four.htm" shape="rect" />
                </map>
                    
                <!-- Использование навигационной панели -->
                <img alt="Навигационная панель" border="0" src="Images/ImageMap.png" usemap="#NavBar" />
            </div>
        </form>
    </body>
    </html>
  • Добавьте к корневому узлу проекта еще четыре статических страницы
  • one.htm
  • two.htm
  • three.htm
  • four.htm
  • Заполните каждую из страниц соответствующим текстом по приведенному образцу
    (рис ) Образец текста для страницы one.htm первой горячей зоны<html>
    <head>
        <title>Untitled Document</title>
        <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
    </head>
    <body>
        <h1>
            Страница вызвана по щелчку на горячей зоне 1
        </h1>
    </body>
    </html>
  • Запустите страницу ImageMap.htm и испытайте ее функциональность
  • Рендеринг страницы ImageMap.htm будет таким

    Мы видим, что страница функционирует, но мы не можим построить для нее сложную логику, поскольку сервером она не обрабатывается, а посылается как есть один раз. Затем в броузере вызываются привязанные к горячим зонам файлы. Здесь на выручку приходит серверный web-элемент ImageMap, который позволяет организовать полноценную навигацию по сайту (с проверками паролей и всех других нужных дел на стороне сервера). На выходе он будет генерировать такой-же клиентский HTML-код, который мы только что рассмотрели.

    При рендеринге элемент управления ImageMap генерирует тег <img usemap="#myMap" /> и тег <map id="myMap" name="myMap"> с вложенными элементами <area>. Элемент управления ImageMap имеет следующие свойства

    Свойства элемента ImageMap
    Свойство Описание
    Enabled Включает или выключает рендеринг элемента
    HotSpots Содержит коллекцию дочерних объектов HotSpot, определяющих горячие зоны
    HotSpotMode Виртуальное свойство, которое устанавливает для дочерних элементов HotSpot (горячих зон) поведение по умолчанию и может быть в них переопределено. Ожидает одно из значений одноименного перечисления System.Web.UI.WebControls.HotSpotMode:
  • Inactive = 3 - никак не реагирует на щелчок мыши
  • Navigate = 1 - вызвать страницу связанного URL
  • NotSet = 0 - поведение устанавливается дочерними элементами самостоятельно (по умолчанию). Если и дочерние элементы не переопределяют это свойство, то используется поведение по умолчанию - вызов страницы по URL
  • PostBack = 2 - при щелчке пользователя просто инициировать обратную отсылку для анализа сервером
  • Target Виртуальное свойство, устанавливающее по умолчанию для своих дочерних элементов HotSpot окно или фрейм, куда сервер должен прислать отклик на щелчек пользователя. В каждом HotSpot оно может быть индивидуально переопределено

    Дочерние для ImageMap элементы управления HotSpot также имеют свои свойства HotSpotMode, имеющие преоритет над родительским HotSpotMode. Если мы хотим, чтобы это свойство принималось от родительского элемента, то в дочернем элементе HotSpot нужно установить значение HotSpotMode=NotSet. Если в родительском и дочернем элементах установлено значение HotSpotMode=NotSet, то HotSpot дочернего элемента работает в режиме Navigate.

    В приведенной таблице под объектами класса HotSpot коллекции HotSpots подразумеваются три разновидности объектов, произведенных его прямыми потомками:

  • Объекты класса CircleHotSpot : HotSpot
  • Объекты класса RectangleHotSpot : HotSpot
  • Объекты класса PolygonHotSpot : HotSpot
  • Именно они ответственны за генерацию тега <area> с нужными параметрами, которые устанавливаются в свойствах объектов этих классов. Других геометрических примитивов для определения горячих зон элемента ImageMap в библиотеке .NET Framework 2.0 не предусмотрено.

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

    Общие свойства, наследуемые от HotSpot
    Свойство Описание
    AccessKey Содержит одиночный символ (горячую клавишу), который составляет вместе с Alt клавиатурную комбинацию прямого вызова вместо щелчка мыши
    AlternateText Текст, отображающийся на месте рисунка при невозможности его загрузки или всплывающую подсказку (генерирует атрибут alt тега <img> )
    HotSpotMode Задает реакцию HotSpot на щелчок мыши. Переопределяет такое же свойство родительского ImageMap. Если в HotSpot установлено HotSpotMode=Inactive, то этот HotSpot никак не реагирует на щелчки мыши. Они применяются для частичного закрытия активных зон при создании интерактивности сложной конфигурации. Закрывающий неактивный HotSpot должен находиться впереди активного в коллекции элемента управления ImageMap
    NavigateUrl URL перехода по щелчку мышью на HotSpot
    PostBackValue Строка, идентифицирующая HotSpot среди аргументов события Click, передаваемая серверу как одноименное свойство в объекте класса ImageMapEventArgs
    TabIndex Определяет очередность получения фокуса конкретного элемента среди коллекции HotSpot в ImageMap
    Target Виртуальное свойство, устанавливающее для HotSpot окно или фрейм, куда сервер должен прислать отклик на щелчек пользователя.

    Приведем пример.

  • Добавьте к проекту в каталог
  • Добавьте к проекту новую страницу с отделенным кодом и именем MyImageMap.aspx. Заполните кодовую часть так
    (рис ) Код наложения на рисунок горячих зон в файле MyImageMap.aspx.csusing 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 MyImageMap : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            lbl = new Label();
            form1.Controls.Add(lbl);
            lbl.Text = String.Empty;// Очистили для тренировки
            //form1.Controls.Add(new HtmlGenericControl("br"));
        
            // Подключаем и настраиваем карту изображений
            ImageMap imageMap = new ImageMap();
            imageMap.EnableViewState = false;   // Отключили сохранение 
                                                // состояния вида
            imageMap.ImageUrl = "~/Images/HotSpot.png";
            imageMap.AlternateText = "Геометрический натюрморт";
            imageMap.HotSpotMode = HotSpotMode.PostBack;
            // Регистрируем два обработчика на одно событие
            imageMap.Click += new ImageMapEventHandler(imageMap_Click1);
            imageMap.Click += new ImageMapEventHandler(imageMap_Click2);
            form1.Controls.Add(imageMap);
        
            // Объявляем ссылки на горячие зоны
            RectangleHotSpot rect;
            PolygonHotSpot star;
            CircleHotSpot circle;
        
            // Создаем и настраиваем горячие зоны:
            // Звезда
            star = new PolygonHotSpot();
            imageMap.HotSpots.Add(star);
            star.Coordinates = "255,0, 280,51, 336,60, 297,100, 306,155,"
                + "255,129, 205,155, 214,100, 173,60, 230,51, 255,0";
            star.PostBackValue = "звезда";
        
            // Описываем активный прямоугольник
            rect = new RectangleHotSpot();
            rect.Left = 0;
            rect.Top = 95;
            rect.Right = 177;
            rect.Bottom = 219;
            rect.PostBackValue = "прямоугольник";
        
            // Описываем неактивный частично закрывающий круг
            CircleHotSpot cirShadow = new CircleHotSpot();
            cirShadow.X = rect.Left + (rect.Right - rect.Left) / 2;
            cirShadow.Y = rect.Top + (rect.Bottom - rect.Top) / 2;
            cirShadow.Radius = (cirShadow.Y - rect.Top) / 2;
            cirShadow.PostBackValue = "пустышка";
            cirShadow.HotSpotMode = HotSpotMode.Inactive;
        
            // Пустышка на переднем фоне, поэтому добавляем первой
            imageMap.HotSpots.Add(cirShadow);
            // Активный элемент частично закрывается пустышкой
            imageMap.HotSpots.Add(rect);
        
            // Круг
            circle = new CircleHotSpot();
            imageMap.HotSpots.Add(circle);
            circle.X = 320;
            circle.Y = 241;
            circle.Radius = 75;
            circle.PostBackValue = "круг";
            
            // Готовим фоновый прямоугольник для всей карты изображений
            // Чтобы был фоновым, нужно в коллекцию добавлять последним
            RectangleHotSpot rectBack = new RectangleHotSpot();
            rectBack.Left = 0;
            rectBack.Top = 0;
            rectBack.Right = 395;
            rectBack.Bottom = 317;
            imageMap.HotSpots.Add(rectBack);
            rectBack.PostBackValue = "фон";
        }
        
        // Первым зарегистрирован, первым и сработает 
        void imageMap_Click1(object sender, ImageMapEventArgs e)
        {
            if (e.PostBackValue != "Фон")
                lbl.Text = String.Format("Вы щелкнули на фигуре \"{0}\"<br>",
                    e.PostBackValue);
            else
                lbl.Text = "Вы промазали!<br>";
        }
        
        // Вторым зарегистрирован, вторым и сработает
        void imageMap_Click2(object sender, ImageMapEventArgs e)
        {
            // Перестраховались только для тренировки,
            // поскольку другого элемента и не будет
            ImageMap imgMap = sender as ImageMap;
            if (imgMap == null)
                return;
        
            // Печатаем список названий горячих зон
            for (int i = 0; i < imgMap.HotSpots.Count; i++)
            {
                lbl.Text += String.Format("- {0}<br>", 
                    imgMap.HotSpots[i].PostBackValue);
            }
        }
        
        Label lbl;// Для видимости в обработчиках объявили как поле
    }
  • Один из откликов сервера на клиенте, если пользователь щелкнет на прямоугольнике, будет выглядеть так

    Обратите внимание, что разметочную часть страницы мы не модифицировали, а все сформировали в динамическом режиме. Если горячие зоны должны частично закрывать друг друга, включая неактивные зоны, то добавление объектов HotSpot в коллекцию HotSpots элемента управления ImageMap должно начинаться с переднего плана по направлению к фону.

    Задание для самостоятельного выполнения

    Разработайте страницу, которая повторяла бы функциональность рассмотренной нами ранее статической страницы ImageMap.htm для рисунка

    Сравните HTML-код, сгенерованный активной страницей, с HTML-кодом статической страницы.

    Расширение стандартного HotSpot

    Стандартные HotSpot могут генерировать только три разновидности фигур: circle, rectangle и polygon. Это связано с ограничением стандартного HTML-дескриптора <area>, у которого атрибут shape может принимать только одно из трех значений "circle", "rect", "poly". Однако на этой основе можно создать более сложные и разнообразные фигуры, расширяя соответствующим образом класс стандартного HotSpot.

    Рассмотрим пример, в котором создадим расширение, способное генерировать активный участок, совпадающий с равнобедренным треугольником. Модель треугольника описывается центральной точкой, шириной и высотой.

  • Создайте новую страницу с разделенным кодом и именем ImageMapExt.aspx
  • Заполните кодовую часть следующим содержимым
  • 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 ImageMapExt : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            lbl = new Label();
            form1.Controls.Add(lbl);
            lbl.Text = String.Empty;// Очистили для тренировки
        
            // Подключаем и настраиваем карту изображений
            ImageMap imageMap = new ImageMap();
            imageMap.EnableViewState = false;   // Отключили сохранение 
            // состояния вида
            imageMap.ImageUrl = "~/Images/TriangleHotSpot.png";
            imageMap.HotSpotMode = HotSpotMode.PostBack;
            // Регистрируем обработчик события щелчка
            imageMap.Click += new ImageMapEventHandler(imageMap_Click1);
            form1.Controls.Add(imageMap);
        
            // Создаем горячую зону в форме треугольника
            TriangleHotSpot triangle = new TriangleHotSpot();
            imageMap.HotSpots.Add(triangle);
            triangle.Width = 200;
            triangle.Height = 300;
            triangle.X = 100;
            triangle.Y = 150;
            triangle.PostBackValue = "треугольник";
        }
        
        Label lbl;
        
        void imageMap_Click1(object sender, ImageMapEventArgs e)
        {
            lbl.Text = String.Format("Вы щелкнули на фигуре \"{0}\"<br>",
                e.PostBackValue);
        }
    }
        
    // Для сохранения значений свойств используем словарь состояния вида	
    public class TriangleHotSpot : System.Web.UI.WebControls.HotSpot
    {
        public TriangleHotSpot()
        {
            Width = Height = X = Y = 0;
            this.AlternateText = "Равнобедренный треугольник";
        }
        
        // Свойства
        public int Width
        {
            get { return (int)ViewState["Width"]; }
            set { ViewState["Width"] = value; }
        }
        
        public int Height
        {
            get { return (int)ViewState["Height"]; }
            set { ViewState["Height"] = value; }
        }
        
        // Координаты центральной точки треугольника
        public int X
        {
            get { return (int)ViewState["X"]; }
            set { ViewState["X"] = value; }
        }
        
        public int Y
        {
            get { return (int)ViewState["Y"]; }
            set { ViewState["Y"] = value; }
        }
        
        // Значение атрибута shape дескриптора <area>
        protected override string MarkupName
        {
            get { return "poly"; }
        }
        
        // Значение атрибута coords дескриптора <area>
        public override string GetCoordinates()
        {
            // Координаты верхнего угла
            int topX = X;
            int topY = Y - Height / 2;
        
            // Координаты левого угла
            int leftX = X - Width / 2;
            int leftY = Y + Height / 2;
        
            // Координаты правого угла
            int rightX = X + Width / 2;
            int rightY = Y + Height / 2;
        
            String str = String.Format("{0},{1}", topX, topY);
            str += "," + String.Format("{0},{1}", leftX, leftY);
            str += "," + String.Format("{0},{1}", rightX, rightY);
        
            return str;
        }
    }

    Рендеринг страницы будет следующим

    Вернуться к учебному плану