Веб-элементы управления

84

Серверные элементы управления HTML предлагают относительно быстрый, но не наилучший способ миграции на ASP. NET, поскольку имена элементов управления HTML и их атрибуты не всегда интуитивно понятны и не обладают одинаковой поддержкой на этапе проектирования для связывания с обработчиками событий. Элементы управления HTML также обладают определенными ограничениями, например, свойства стилей должны устанавливаться с применением синтаксиса CSS (более сложного, чем установка прямого свойства), а события изменения не могут генерироваться до тех пор, пока страница не будет отправлена в ответ на другое действие.

Наконец, серверные элементы управления HTML не могут предоставить элементы пользовательского интерфейса, которые пока не определены стандартом HTML. Если вы собираетесь создать какой-либо групповой элемент управления, использующий сочетание элементов HTML для построения сложного интерфейса, вам придется делать это самостоятельно.

Для решения этих проблем ASP.NET предоставляет высокоуровневую модель веб-элементов управления. Все веб-элементы управления определены в пространстве имен System.Web.UI.WebControls и являются производными от базового класса WebControl, реализующего более абстрактную и согласованную модель, чем модель серверных элементов управления HTML. Веб-элементы управления также поддерживают дополнительные средства, такие как автоматическая обратная отправка. Но действительно примечательным является то, что многие усовершенствованные элементы управления не просто отображаются на отдельный HTML-дескриптор, но генерируют более сложный вывод, состоящий из нескольких HTML-дескрипторов и JavaScript-кода. В качестве примеров можно привести списки флажков, переключатели, календари, редактируемые сетки и т.д.

Ниже показана часть иерархии наследования веб-элементов управления:

Веб-элементы управления

Базовый класс WebControl

Все веб-элементы управления унаследованы от класса WebControl. Сам класс WebControl, в свою очередь, наследуется от Control. Поэтому многие его свойства и методы, например, Controls, Visible и FindControl(), похожи на свойства и методы серверных элементов управления HTML. Однако класс WebControl добавляет еще и свойства, перечисленные ниже:

Свойства класса WebControl
Свойство Описание
AccessKey Возвращает или устанавливает сокращенную клавиатурную комбинацию, позволяющую быстро переместиться на элемент управления. Например, при установке в А пользователь может переместить фокус на этот элемент управления, нажав комбинацию <Alt+A>
BackColor Возвращает или устанавливает цвет фона
BorderColor Возвращает или устанавливает цвет границы
BorderStyle Одно из значений перечисления BorderStyle: Dashed, Dotted, Double, Groove, Ridge, Inset, Outset, Solid и None
BorderWidth Возвращает или устанавливает ширину границы
CssClass Возвращает или устанавливает стиль CSS для элемента управления. Стиль CSS может быть определен в разделе <style> в верхней части страницы или же в отдельном файле CSS, на который ссылается страница
Enabled Возвращает или устанавливает активизированное состояние элемента управления. При значении false элемент управления становится неактивным (отображается серым цветом)
Font Возвращает объект со всей информацией о стилях шрифта, используемого для текста элемента управления
ForeColor Возвращает или устанавливает цвет изображения, например, цвет текста элемента управления
Height Возвращает или устанавливает высоту элемента управления
TabIndex Число, позволяющее управлять порядком обхода по клавише <ТаЬ>. Элемент управления с нулевым TabIndex получает фокус при первой загрузке страницы. Нажатие клавиши <ТаЬ> перемещает пользователя на элемент управления со следующим наиболее низким TabIndex при условии, что он активен. Это свойство поддерживается только в браузере Internet Explorer 4.0 и в последующих его версиях
Tooltip Отображает текстовое сообщение, когда пользователь наводит на элемент управления курсор мыши. Во многих более старых браузерах это свойство не поддерживается
Width Возвращает или устанавливает значение ширины элемента управления

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

Базовые классы веб-элементов управления

В состав ASP.NET входят веб-элементы управления, дублирующие каждый из серверных элементов управления HTML и предоставляющие точно такие же функциональные возможности. Эти веб-элементы управления унаследованы от класса WebControl и вдобавок имеют ряд собственных свойств и событий. Все они кратко перечислены в следующей таблице:

Базовые классы веб-элементов управления
Объявление дескриптора ASP.NET Генерируемая HTML-разметка Ключевые члены
<asp:Button> <input type="submit"/> или <input type="button"/> Text, CausesValidation, PostBackUrl, ValidationGroup, событие Click
<asp:CheckBox> <input type="checkbox"/> AutoPostBack, Checked, Text, TextAlign, событие CheckedChanged
<asp:FileUpload> <input type="file"> FileBytes, FileContent, FileName, HasFile, PostedFile, SaveAs()
<asp:HiddenField> <input type="hidden"> Value
<asp:HyperLink> <a>...</a> ImageUrl, NavigateUrl, Target, Text
<asp:Image> <img/> AlternateText, ImageAlign, ImageUrl
<asp:ImageButton> <input type="image"/> CausesValidation, ValidationGroup, событие Click
<asp:ImageMap> <map> HotSpotMode, HotSpots (коллекция), AlternateText, ImageAlign, ImageUrl
<asp:Label> <span>...</span> Text, AssociatedControlID
<asp:LinkButton> <a><img/></a> Text, CausesValidation, ValidationGroup, событие Click
<asp:Panel> <div>...</div> BackImageUrl, DefaultButton, GroupingText, HorizontalAlign, Scrollbars, Wrap
<asp:RadioButton> <input type="radio"/> AutoPostBack, Checked, GroupName, Text, TextAlign, событие CheckedChanged
<asp:Table> <table>...</table> BackImageUrl, CellPadding, Cellspacing, GridLines, HorizontalAlign, Rows (коллекция)
<asp:TableCell> <td>...</td> ColumnSpan, HorizontalAlign, RowSpan, Text, VerticalAlign, Wrap
<asp:TableRow> <tr>...</tr> Cells (коллекция), HorizontalAlign, VerticalAlign
<asp:TextBox> <input type="text"/> или <textarea>...</textarea> AutoPostBack, Columns, MaxLength, Readonly, Rows, Text, TextMode, Wrap, событие TextChanged

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

Для начала ознакомления с некоторыми ключевыми отличиями между серверными элементами управления HTML и веб-элементами управления рассмотрим следующий дескриптор веб-элемента управления:

<asp:TextBox runat="server" ID="TextBox1" Text="Простой текст"
            ForeColor="red" BackColor="lightyellow" Width="250px"
            Font-Bold="True" Font-Names="Verdana" Font-Size="20" />

Веб-элементы управления всегда объявляются на странице с использованием синтаксиса <asp:ИмяЭлементаУправления>, при этом префикс asp: упрощает их распознавание. Однако представленный пример также демонстрирует более значительное отличие — способ указания информации о стилях.

По сути, этот дескриптор генерирует текстовое поле шириной в 250 пикселей, с красным цветом переднего плана и светло-желтым цветом фона. Текст выводится шрифтом Verdana размером 20 и полужирным начертанием. Ниже описаны различия между предыдущим объявлением и соответствующим объявлением дескриптора HTML:

Если запросить страницу с таким дескриптором, то при ее визуализации соответствующий элемент управления будет преобразован в следующий дескриптор HTML:

<input name="TextBox1" type="text" value="Простой текст" id="TextBox1"
   style="color:Red;background-color:LightYellow;font-family:Verdana;font-size:20pt;font-weight:bold;width:250px;" />

Единицы измерения

Все свойства элементов управления, использующие размеры, в том числе BorderWidth, Height и Width, требуют структуры Unit, комбинирующей числовое значение с единицей измерения (пиксели, проценты и т.п.). Это означает, что при установке этих свойств в дескрипторе элемента управления вы должны добавить к числу рх (для пикселей) или % (для процентов) для указания типа единицы измерения.

Ниже приведен пример с элементом управления Panel, высота которого равна 300 пикселей, а ширина составляет 50 процентов размера текущего окна браузера:

<asp:Panel ID="panel" runat="server" Height="300px" Width="50%" BackColor="#6699ff">

При установке основанного на единицах свойства в коде необходимо использовать один из статических методов типа Unit. Применяйте Pixel() для значения в пикселях и Percentage() — для значения в процентах:

// Задание высоты панели в пикселях
panel.Height = Unit.Pixel(300);

// Задание ширины панели в процентах
panel.Width = Unit.Percentage(50);

Перечисления

Перечисления активно используются в библиотеке классов .NET для группирования наборов связанных констант. Например, при установке свойства BorderStyle элемента управления можно выбрать одно из нескольких предопределенных значений из перечисления BorderStyle. В коде перечисление задается с использованием точечного синтаксиса:

TextBox1.BorderStyle = BorderStyle.Dashed;

В файле .aspx перечисление устанавливается за счет указания в строке одного из допустимых значений. Имя перечислимого типа не задается, а определяется автоматически.

Цвета

Свойство Color относится к объекту Color из пространства имен System.Drawing. Объекты Color можно создавать несколькими способами:

Для использования одного из этих методов потребуется импортировать пространство имен System.Drawing:

using System.Drawing;

В следующем коде демонстрируется несколько способов определения цвета:

// Создать цвет с использованием значения ARGB
int alpha = 255, red = 0, green = 255, blue = 55;
panel.BackColor = Color.FromArgb(alpha, red, green, blue);

// Создать цвет с использованием имени из .NET
TextBox1.ForeColor = Color.Crimson;

// Создать цвет с использованием кода HTML
TextBox1.BorderColor = ColorTranslator.FromHtml("orange");

Полный список имен цветов можно найти в документации Visual Studio. В качестве альтернативы можно использовать шестнадцатеричное представление цвета (в формате #<красный><зеленый><синий>), как показано ниже:

<asp:Panel ID="panel" runat="server" BackColor="#6699ff">

Шрифты

Свойство Font в действительности ссылается на полный объект FontInfo, определение которого содержится в пространстве имен System.Web.UI.WebControls. Каждый объект FontInfo имеет несколько свойств, которые определяют имя, размер и стиль шрифта. Хотя свойство WebControl.Font доступно только для чтения, все свойства FontInfo (перечисленные ниже) можно изменять:

Свойства FontInfo
Свойство Описаниеs
Name Строка, обозначающая имя шрифта (например, Verdana)
Names Массив строк с именами шрифтов, которые упорядочиваются согласно имеющимся предпочтениям
Size Размер шрифта в форме объекта FontUnit. Может представлять абсолютный или относительный размер
Bold, Italic, Strikeout, Underline и Overline Булевские свойства, которые либо применяют данный атрибут стиля, либо игнорируют его

В коде можно присваивать значения различным свойствам шрифта:

TextBox1.Font.Name = "Verdana";
TextBox1.Font.Bold = true;

// Можно также установить размер с использованием типа FontUnit
TextBox1.Font.Size = FontUnit.Small;
TextBox1.Font.Size = FontUnit.Point(14);

В файле .aspx следует применять специальный синтаксис прохода по объекту для определения таких свойств объекта, как шрифт. Синтаксис прохода по объекту использует дефис (-) для разделения свойств.

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

Чтобы предоставить список возможных шрифтов, вместо свойства FontInfo.Name необходимо использовать свойство FontInfo.Names. Свойство Names принимает в качестве значения массив имен, которые будут визуализироваться в виде упорядоченного списка (причем наиболее предпочитаемые имена будут отображаться в самом верху этого списка). Например:

<asp:TextBox runat="server" ID="TextBox1" Font-Names="Verdana, Calibri, Times New Roman" />

Свойства Names и Name поддерживаются в синхронизированном состоянии, и установка значения для одного из них обязательно влияет на другое. Например, когда устанавливается значение для свойства Names, свойству Name автоматически присваивается первый элемент из массива, который был указан для свойства Names. Если же устанавливается значение для свойства Name, свойству Names автоматически присваивается массив, состоящий из единственного элемента. Поэтому использовать нужно только либо Name, либо Names, но ни в коем случае не оба свойства одновременно.

Фокус

В отличие от серверных элементов управления HTML, каждый веб-элемент управления предоставляет метод Focus(). Фокус оказывает влияние только на элементы управления вводом (элементы управления, принимающие нажатия клавиш от пользователя). После визуализации страницы в клиентском браузере пользователь начинает работу с элемента управления, имеющего фокус.

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

После визуализации страницы пользователь может перемещаться между элементами управления с использованием хорошо известной клавиши <ТаЬ>.

Конечно, если вы знакомы со стандартом HTML, то знаете, что не существует встроенного способа передачи фокуса элементу управления вводом. В этом следует полагаться на JavaScript-код. Здесь-то и кроется секрет реализации ASP.NET. В конце сгенерированного кода страницы ASP.NET добавляет дополнительный блок JavaScript-кода. Этот JavaScript-код просто устанавливает фокус на последний элемент управления с инициированным методом Focus().

Ниже показан код, который ASP.NET добавит к визуализируемой веб-странице для перемещения фокуса на элемент управления по имени TextBox2:

WebForm_AutoFocus('TextBox2');

Если вы вообще не вызывали метод Focus(), этот код не генерируется. Если вы вызывали его для нескольких элементов управления, то JavaScript-код выбирает элемент управления, получивший фокус раньше других.

Вместо программного вызова метода Focus() установить элемент управления, который должен всегда иметь фокус, можно в разметке. Это делается с помощью свойства DefaultFocus следующим образом:

<form id="form1" runat="server" defaultfocus="TextBox2">

Кстати, код фокусировки полагается на JavaScript-метод по имени WebForm_AutoFocus(), который автоматически генерируется ASP.NET. Формально JavaScript-метод предоставляется с помощью расширения ASP.NET под названием WebResource.axd. Ресурс имеет имя Focus.js. Если вы просмотрите сгенерированный HTML-код своей страницы, то легко обнаружите там ссылающийся на этот JavaScript-файл элемент, который будет выглядеть приблизительно так (с длинными аргументами d и t):

<script src="/WebResource.axd?d=...&t=..." type="text/javascript"></script>

Этот запрос можно ввести прямо в браузере для загрузки и просмотра документа JavaScript. Он довольно длинный, поскольку в нем уделяется много внимания таким случаям, как передача фокуса нефокусируемому элементу управления, который содержит дочерний элемент управления с возможностью фокусировки. В следующем коде демонстрируется сущность логики передачи фокуса:

function WebForm_AutoFocus(focusId) {
    // Найти элемент по его идентификатору (код отличается 
    // в зависимости от браузера)
    
    var targetControl;
    if (__nonMSDOMBrowser) {
        targetControl = document.getElementById(focusId);
    }
    else {
        targetControl = document.all[focusId];
    }
    
    // Проверить, может ли элемент управления получать фокус, и если нет, то 
    // не содержит ли он дочерний элемент управления, который может его получать

    var focused = targetControl;
    if (targetControl && (!WebForm_CanFocus(targetControl)) ) {
        focused = WebForm_FindFirstFocusableChild(targetControl);
    }
    
    // В случае обнаружения подходящего элемента управления, попытаться 
    // применить к нему фокус и прокрутить страницу, чтобы он стал виден
    
    if (focused) {
        try {
            focused.focus();
            if (__nonMSDOMBrowser) {
                focused.scrollIntoView(false);
            }
            if (window.__smartNav) {
                window.__smartNav.ae = focused.id;
            }
        }
        catch (e) {
        }
    }
}

Как видите, первая задача, решаемая этим кодом, состоит в проверке того, является ли текущий браузер одной из новых версий Internet Explorer (т.е. поддерживает ли он модель Microsoft DOM). Если он таковым не является, код сценария все равно выполняет автофокусировку, но с незначительными различиями.

Кнопка по умолчанию

Помимо механизма фокусировки на элементах управления, в состав ASP.NET также входит механизм, позволяющий назначать на веб-странице кнопку по умолчанию, т.е. кнопку, на которой должен выполняться "щелчок" в случае нажатия пользователем клавиши <Enter>.

Например, в форме такой кнопкой удобно сделать кнопку Submit. Тогда в каком бы месте пользователь не нажал <Enter>, будет инициироваться обратная отправка страницы и генерироваться событие Button.Click для этой кнопки.

Чтобы назначить кнопку по умолчанию, нужно указать в свойстве HtmlForm.DefaultButton идентификатор соответствующего элемента управления:

<form id="Form1" DefaultButton="cmdSubmit" runat="server">

В роли кнопки по умолчанию может выступать только элемент управления, реализующий интерфейс IButtonControl. Этот интерфейс реализуют такие веб-элементы управления, как Button, LinkButton и ImageButton, но ни один из серверных элементов управления HTML.

В некоторых случаях требуется иметь несколько кнопок по умолчанию. Например, может понадобиться создать веб-страницу с двумя группами элементов управления вводом, у каждой из которых должна быть своя кнопка по умолчанию. Решить этот вопрос поможет размещение этих групп в отдельных панелях, т.е. отдельных элементах управления Panel. Элемент управления Panel тоже предоставляет свойство DefaultButton, которое начинает действовать тогда, когда любой содержащийся в нем элемент управления вводом получает фокус.

Прокручиваемые панели

Элемент управления Panel обладает возможностью прокрутки. Это означает, что элементы управления Panel можно заполнить любыми серверными элементами управления либо элементами HTML, явно установить значения их свойств Height и Width, чтобы они никогда не оказывались меньше требуемых, и затем включить возможность прокрутки, указав для их свойства ScrollBars значение Vertical, Horizontal, Both или Auto (при котором полосы прокрутки отображаются только тогда, когда содержимое не умещается):

<asp:Panel ID="panel" runat="server" BackColor="#6699ff" 
   Height="185px" Width="350px" ScrollBars="Auto">
      ...
Прокручиваемая панель

Панель визуализируется как дескриптор <div>. Поведение прокрутки обеспечивается путем установки значения для CSS-свойства overflow.

Обработка событий веб-элементов управления

События веб-элементов управления работают так же, как и серверные события серверных элементов управления HTML. Событие ServerClick заменяется событием Click, а общие события ServerChange — специфическими событиями CheckedChanged (для RadioButton и CheckButton) и TextChanged (для TextBox), но их поведение остается таким же.

Основное различие состоит в том, что веб-элементы управления поддерживают свойство AutoPostBack, которое использует JavaScript для захвата клиентского события и запуска обратной отправки. ASP.NET получает отправленную страницу и немедленно запускает соответствующее серверное событие.

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

В данном примере все события смены элементов управления обрабатываются одним и тем же обработчиком:

<form id="form1" runat="server">
        <div>
            <h3>Список событий:</h3>
            <asp:ListBox ID="lstEvents" runat="server" Height="107px" Width="355px"></asp:ListBox><br />
            <h3>Элементы управления вводом:</h3>
            <asp:TextBox ID="TextBox" runat="server" AutoPostBack="True" OnTextChanged="CtrlChanged"></asp:TextBox><br />
            <br />
            <asp:CheckBox ID="CheckBox" runat="server" AutoPostBack="True" OnCheckedChanged="CtrlChanged"></asp:CheckBox><br />
            <br />
            <asp:RadioButton ID="RadioButton1" runat="server" GroupName="Sample" AutoPostBack="True" 
                OnCheckedChanged="CtrlChanged"></asp:RadioButton>
            <asp:RadioButton ID="RadioButton2" runat="server" GroupName="Sample" AutoPostBack="True"
                OnCheckedChanged="CtrlChanged"></asp:RadioButton>
        </div>
</form>

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

protected void CtrlChanged(Object sender, EventArgs e)
{
        string ctrlName = ((Control)sender).ID;
        lstEvents.Items.Add(ctrlName + " Changed");

        // Выбрать последний элемент, чтобы список прокрутился 
        // и последние записи стали видимыми
        lstEvents.SelectedIndex = lstEvents.Items.Count - 1;
}
Приложение для отслеживания событий

Автоматическая обратная отправка не всегда приносит только пользу. Отправка страницы обратно серверу на некоторое время прерывает работу пользователя. Если страница имеет большие размеры, задержка в работе может стать довольно заметной. Если страница является довольно длинной, и пользователь успел прокрутить ее до конца, то при ее обновлении он утратит текущую позицию и будет снова возвращен в начало страницы. Из-за этих особенностей всегда лучше тщательно взвешивать, действительно ли обратная отправка столь необходима, и стараться не применять ее просто в "косметических" целях. В качестве одного из альтернативных вариантов можно использовать вместо нее функциональные возможности AJAX.

Пройди тесты
Лучший чат для C# программистов