ГЛАВА 33 Веб-элементы управления, мастер-страницы и темы ASP.NET предыдущей главе внимание было сосредоточено на композиции и поведении объектов Раде в ASP.NETT. В этой главе мы погрузимся в детали веб-элементов управления, которые составляют пользовательский интерфейс страницы. После рас­ смотрения общей природы веб-элемента управления ASP. NETT вы получите представле­ ние о том, как правильно использовать некоторые элементы пользовательского интер­ фейса, включая элементы управления проверкой достоверности и элементы управления привязкой данных. Значительная часть этой главы будет посвящена роли мастер-страниц. Будет по­ казано, как они обеспечивают упрощенный способ определения общего скелета пользо­ вательского интерфейса, который повторяется среди страниц веб-сайта. С темой мас­ тер-страниц тесно связано использование элементов управления навигацией по сайту (а также файл * . sitem ap), которые позволяют определять навигационную структуру многостраничного сайта с помощью XML-файла серверной стороны. В завершение вы узнаете о роли тем ASP. NETT. Концептуально темы служат той же цели, что и каскадные таблицы стилей; однако темы ASP.NETT применяются на веб-сер­ вере (в противоположность браузеру клиентской стороны) и потому имеют доступ к ре­ сурсам серверной стороны. В Природа веб-элементов управления Ставным преимуществом ASP. NETT является возможность собирать пользовательский интерфейс страниц, используя типы, определенные в пространстве имен System.Web. U l.W ebC ontrols. Как было показано, эти элементы управления (которые называются серверными элементами управления, веб-элементами управления или элементами управления Web Forms) исключительно полезны в том, что автоматически генерируют необходимую HTML-разметку для запрашивающего браузера и предоставляют набор событий, которые могут быть обработаны на веб-сервере. Более того, поскольку каж­ дый элемент управления ASP. NETT имеет соответствующий класс в пространстве имен 1 2 58 Часть VII. Построение веб-приложений с использованием ASP.NET System.Web.UI.WebControls, им можно манипулировать в объектно-ориентированной манере. При конфигурировании свойств веб-элемента управления в окне Properties (Свойства) среды Visual Studio 2010 изменения фиксируются в открывающем дескрипторе объяв­ ления данного элемента в файле *.aspx как последовательность пар “имя/значение”. Таким образом, если добавить новый элемент TextBox в визуальном конструкторе и из­ менить его свойства ID, BorderStyle, BorderWidth, BackColor и Text, открывающий дескриптор <asp:TextBox> будет соответствующим образом модифицирован (обратите внимание, что значение Text становится внутренним текстом в области TextBox): <asp:TextBox ID="txtNameTextBox" runat="server" BackColor="#C0FFC0" BorderStyle="Dotted" BorderWidth="3px">Enter Your Name</asp:TextBox> Учитывая, что это объявление веб-элемента управления в конечном итоге становит­ ся переменной-членом из пространства имен System.Web.UI.WebControls (через цикл динамической компиляции, рассмотренный в главе 32), с членами этого типа можно взаимодействовать внутри блока <script> серверной стороны или в файле отделенно­ го кода. Добавив в файл *.aspx новый элемент управления Button, можно написать обработчик события Click серверной стороны, в котором будет изменяться цвет фона элемента TextBox: partial class _Default : System.Web.UI.Page { protected void btnChangeTextBoxColor_Click(object sender, System.EventArgs e) { // Изменить цвет объекта TextBox в коде. this.txtNameTextBox.BackColor = System.Drawing.Color.DarkBlue; } } Все веб-элементы управления ASP.NET в конечном итоге наследуются от общего базового класса System.Web.UI.WenControls.WebControl, который, в свою очередь, унаследован от System.Web.UI.Control (а тот — от System.Object). И Control, и WebControl определяют ряд свойств, общих для всех элементов управления серверной стороны. Прежде чем рассмотреть унаследованную функциональность, давайте форма­ лизуем понятие обработки событий серверной стороны. Обработка событий серверной стороны Учитывая текущее состояние World Wide Web, нельзя не принимать во внимание фундаментальную природу взаимодействия браузеров с веб-серверами. Всякий раз, ко­ гда эти две сущности взаимодействуют, возникает лишенный состояния цикл запроса/ ответа HTTP. Хотя серверные элементы управления ASP. NETT выполняют большую ра­ боту, изолируя от низкоуровневых деталей протокола HTTP, всегда стоит помнить, что восприятие WWW как управляемой событиями сущности — всего лишь маскировка, ко­ торую обеспечивает CLR, и не имеет ничего общего с управляемой событиями модели пользовательских интерфейсов на основе Windows. Так, например, хотя пространства имен System.Windows.Forms, System.Windows. Controls и System.Web.UI.WebControls определяют типы с теми же простыми имена­ ми (Button, TextBox, Label и т.д.), они не предоставляют идентичных наборов событий. Например, не существует способа обработать событие серверной стороны MouseMove, когда пользователь перемещает курсор над элементом управления Web Forms типа Button. Очевидно, что это хорошо (вряд ли кому понадобится выполнять обратную от­ правку на сервер при каждом движении курсора мыши в браузере). Глава 33. Веб-элементы управления, мастер-страницы и темы ASP.NET 12 59 Отрицательным фактором является то, что данный веб-элемент управления ASP.NETT поддерживает ограниченный набор событий, и все они в конечном итоге подразумевают обратную отправку на веб-сервер. Любая необходимая обработка событий клиентской стороны потребует написания массы сценарного кода JavaScript /VBScript клиентской стороны для обработки механизмом выполнения сценариев запросившего браузера. Учитывая то, что ASP.NETT — это в первую очередь технология серверной стороны, тема написания сценариев клиентской стороны здесь не рассматривается. На заметку! Обработка события для определенного веб-элемента управления с использовани­ ем Visual Studio 2010 может быть выполнена в той же манере, что и для элемента управления Windows Forms. Просто выберите необходимый виджет на поверхности визуального конструк­ тора и щелкните на значке с изображением молнии в окне Properties. Свойство A u t o P o s t B a c k Стоит также упомянуть, что многие веб-элементы управления ASP.NETT поддержи­ вают свойство по имени AutoPostBack (прежде всего, элементы управления CheckBox, RadioButton и TextBox, а также любые элементы, унаследованные от абстрактного класса ListControl). По умолчанию это свойство установлено в false, что отключает немедленную обратную отправку на сервер (даже при наличии обработчика события в файле отделенного кода). В большинстве случаев это именно то поведение, которое нужно, учитывая, что такие элементы, как флажки, обычно не требуют функциональ­ ности обратной отправки. Другими словами, не нужно выполнять обратную отправку немедленно после отметки или снятия отметки с флажка, поскольку объект страницы может получить состояние виджета внутри более естественного обработчика события Click для Button. Однако если необходимо заставить любой из этих виджетов немедленно выполнять обратную отправку обработчику события серверной стороны, установите значение AutoPostBack равным true. Такая техника полезна, когда требуется сделать так, чтобы состояние одного виджета автоматически помещало значение в другой виджет на той же странице. Для иллюстрации предположим, что есть веб-страница, содержащая элемент TextBox (по имени txtAutoPostback) и элемент ListBox (по имени IstTextBoxData). Ниже показана соответствующая разметка: <form id="forml" runat="server"> <asp:TextBox ID="txtAutoPostback" runat="server"></asp:TextBox> <br/> <asp :ListBox ID="IstTextBoxData" runat="server"x/asp :ListBox> </form> Теперь обработайте событие TextChanged элемента TextBox, и внутри обработчика событий серверной стороны заполните ListBox текущим значением TextBox: partial class _Default : System.Web.UI .Page { protected void txtAutoPostback_TextChanged(object sender, System.EventArgs e) { IstTextBoxData.Items.Add(txtAutoPostback.Text); } } Если вы запустите приложение в том виде, как есть, то при вводе текста в TextBox обнаружите, что ничего не происходит. Более того, если вы введете что-то в TextBox и перейдете к следующему элементу управления нажатием клавиши <ТаЬ>, также ниче­ 1 2 60 Часть VII. Построение веб-приложений с использованием ASP.NET го не произойдет. Причина в том, что по умолчанию свойство AutoPostBack элемента TextBox установлено в false. Если его установить в true: <asp:TextBox ID="txtAutoPostback" runat="server" AutoPostBack="true"> </asp:TextBox> то при выходе из TextBox по нажатию <Tab> или <Enter> элемент ListBox автомати­ чески заполнится текущим значением TextBox. Честно говоря, помимо необходимости наполнения элементов одного виджета в зависимости от значения другого, обычно из­ менять состояние свойства AutoPostBack виджета не придется (и даже в такой ситуа­ ции задачу можно решить внутри клиентского сценария, исключая необходимость во взаимодействии с сервером). Базовые классы Control и WebControl Базовый класс System.Web.UI.Control определяет различные свойства и события, которые обеспечивают возможность взаимодействия с основными (обычно не имею­ щими отношения к графическому интерфейсу) аспектами веб-элемента управления. В табл. 33.1 документированы некоторые члены, представляющие интерес. Таблица 33.1. Избранные члены S y s te m .W e b .U I .C o n tro l Член Назначение Controls Это свойство получает объект ControlCollection, представляющий дочерние элементы управления внутри текущего элемента DataBindO Этот метод привязывает источник данных к вызывающему серверному элементу управления и всем его дочерним элементам EnableTheming Это свойство устанавливает, поддерживает ли элемент функциональность тем (значение по умолчанию — true) HasControls () Этот метод определяет, содержит ли серверный элемент управления ка­ кие-то дочерние элементы ID Это свойство получает и устанавливает программный идентификатор сер­ верного элемента управления Page Это свойство получает ссылку на экземпляр Раде, который содержит дан­ ный серверный элемент управления Parent Это свойство получает ссылку на родительский элемент данного сервер­ ного элемента управления в иерархии элементов управления страницы SkinID Это свойство получает или устанавливает обл ож ку для применения к эле­ менту управления, позволяя определять внешний вид и поведение с ис­ пользованием ресурсов серверной стороны Visible Это свойство получает и устанавливает значение, указывающее на то, бу­ дет ли серверный элемент управления визуализироваться в виде элемента пользовательского интерфейса на странице Перечисление содержащихся элементов управления Первый аспект System.Web.UI.Control, который мы рассмотрим — это тот факт, что все веб-элементы управления (включая Раде) наследуют коллекцию специальных элементов (доступную через свойство Controls). Во многом подобно приложениям Windows Forms, свойство Controls предоставляет доступ к строго типизованной кол­ Глава 33. Веб-элементы управления, мастер-страницы и темы ASP.NET 1261 лекции типов, унаследованных от WebControl. Подобно любой коллекции .NET, име­ ется возможность динамически добавлять, вставлять и удалять элементы во время выполнения. Хотя технически возможно добавлять новые элементы управления непосредст­ венно к типу-наследнику Раде, проще (и надежнее) использовать элемент управления Panel. Класс Panel представляет контейнер виджетов, которые могут или не могут быть видимы конечному пользователю (в зависимости от значений свойств Visible и BorderStyle). Для примера создайте новый пустой веб-сайт по имени DynamicCtrls. С помощью визуального конструктора страниц Visual Studio 2010 добавьте элемент типа Panel (с именем myPanel), который содержит в себе элементы TextBox, Button и HyperLink, названные как угодно (имейте в виду, что визуальный конструктор требует, чтобы внутренние элементы перетаскивались только в пределах пользовательского интер­ фейса элемента Panel). Затем за пределами Panel разместите виджет Label (по имени lblControlInfo) для помещения в него визуализированного вывода. Ниже показана одна из возможных HTML-разметок. <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Dynamic Control Test</title> </head> <body> <form id="forml" runat="server"> <div> <hr /> <hl>Dynamic Controls</hl> <asp:Label ID="lblTextBoxText" runat="server"x/asp :Label> <hr /> </div> < 1— Элемент Panel содержит три элемента управления — > <asp:Panel ID="myPanel" runat="server" Width="200px" BorderColor="Black" BorderStyle="Solid" > <asp:TextBox ID="TextBoxl" runat="server"></asp:TextBox><br/> <asp:Button ID="Buttonl" runat="server" Text="Button"/><br/> <asp:HyperLink ID="HyperLinkl" runat="server">HyperLink </asp:HyperLink> </asp:Panel> <br /> <br /> <asp:Label ID="lblControlInfo" runat="server"x/asp: Label> </form> </body> </html> С этой разметкой поверхность визуального конструктора страницы будет выглядеть примерно так, как показано на рис. 33.1. Предположим, что в событии Page_Load() необходимо получить детальную инфор­ мацию об элементах управления, содержащихся внутри Panel, и присвоить результат элементу lblControlInfo типа Label. Ниже приведен соответствующий код С#. public partial class _Default : System.Web.U I .Page { private void ListControlsInPanel() { string thelnfo = thelnfo = string. Format ("<b>Does the panel have controls? {0} </bxbr/>", myPanel.HasControls ()); 1 2 62 Часть VII. Построение веб-приложений с использованием ASP.NET // Получить все элементы управления в панели. foreach (Control с in myPanel.Controls) { if (!object.ReferenceEquals(c.GetType (), typeof(System.Web.UI.LiteralControl))) { thelnfo thelnfo thelnfo thelnfo += += += += += • string.Format("Control Name? {0} <br/>", c .ToString()); string.Format("ID? {0} <br>", c.ID); string.Format("Control Visible? {0} <br/>", c.Visible); string.Format("ViewState? {0} <br/>", c .EnableViewState); } } lblControlInfо .Text = thelnfo; } protected void Page_Load(object sender, System.EventArgs e) { ListControlsInPanel (); } } I [tetdurt.aspx cs Object Browser Dynamic Controls pbITextBoxTextJ I a s p :P a n d *m y P an d i Button j H\perLmk L---------------------------------CD--------------------------------- !0 [IbIControilnfo] Design | О Split i^i Source jLbody>JjTfопт*»c rrl~ > ] <asp:Panel*rrtyPanel> [►! Рис. 33.1. Пользовательский интерфейс веб-страницы Dynamic Controls В коде осуществляется проход по всем WebControl, содержащимся в Panel, с про­ веркой их принадлежности к типу System.Web.UI.LiteralControl; элементы этого типа пропускаются. Класс LiteralControl служит для представления литеральных HTML-дескрипторов и содержимого (такого как <br>, текстовые литералы и т.п.). Если не выполнить такую проверку, в контексте Panel будет найдено намного больше эле­ ментов управления (исходя из приведенного выше объявления *.aspx). Предполагая, что элемент управления не является литеральным HTML-содержимым, для него выво­ дятся некоторые статистические данные. Результат можно видеть на рис. 33.2. Динамическое добавление и удаление элементов управления Предположим, что необходимо модифицировать содержимое Panel во время выполнения. Давайте поместим на текущую страницу элемент Button (по имени bntAddWidgets), который будет динамически добавлять к Panel три элемента управ­ ления TextBox, и еще один элемент Button (по имени btnRemovePanelItems), который очистит Panel от всех вложенных элементов управления. Обработчики события Click для обеих кнопок показаны ниже. Глава 33. Веб-элементы управления, мастер-страницы и темы ASP.NET 1263 protected void btnClearPanel_Click(object sender, System.EventArgs e) { // Очистить содержимое панели, затем заново перечислить элементы. myPanel.Controls.Clear(); ListControlsInPanel() ; } protected void btnAddWidgets_Click(object sender, System.EventArgs e) { for (int 1 = 0 ; l < 3; i++) { // Присвоить идентификатор, чтобы можно было // позднее получить текстовое значение / / с использованием входных данных формы. TextBox t = new TextBoxO ; t .ID = string.Format("newTextBox{0 , 1 ); myPanel.Controls.Add(t); ListControlsInPanel (); } } Обратите внимание, что каждому элементу TextBox присваивается уникальный идентификатор (newTextBoxO, newTextBoxl и т. д.). Запустив страницу, можно добав­ лять новые элементы к элементу управления Panel и полностью очищать содержимое Panel. С ft it Wtp locaihost ► О - A - Dynamic Controls Button I B perLm k Does the panel have controls? True Control N am e'1 Svstem W e b U I W ebControls TextBox I D " TextBox 1 Control Visible7 True View State'1 True Control N a m e" System W e b U I WebControIs Button I D " Button 1 Control Visible" True \ tew State0 True Control N a m e " System W e b U I W ebControIs HvperLmk I D " HvperLm k 1 Control Visible7 True ViewState0 True Рис. 33.2. Перечисление элементов управления во время выполнения Взаимодействие с динамически созданными элементами управления Получать значения из этих динамически сгенерированных элементов TextBox мож­ но различными способами. Добавьте к пользовательскому интерфейсу еще один эле­ мент управления Button (по имени btnGetTextData) и один элемент Label по имени lblTextBoxData, а также обработайте событие Click элемента Button. 1 2 6 4 Часть VII. Построение веб-приложений с использованием ASP.NET Для доступа к данным в динамически сгенерированных элементах TextBox есть не­ сколько вариантов. Один подход заключается в циклическом проходе по всем элементам, содержащимся во входных данных формы HTML (доступных через HttpRequest.Form) и накоплении текстовой информации в локальной строке System.String. После прохож­ дения всей коллекции эту строку необходимо присвоить свойству Text нового элемента Label. protected void btnGetTextData_Click(object sender, System.EventArgs e) { string textBoxValues = for (int i = 0 ; l < Request.Form.Count; i++) { textBoxValues += string.Format ("<li> {0 }</lixbr/>" , Request.Form [l]) ; } lblTextBoxData.Text = textBoxValues; } Запустив приложение, вы обнаружите, что содержимое каждого текстового поля можно просматривать в виде довольно длинной (нечитабельной) строки. Эта строка со­ держит состояние представления (view state) каждого элемента управления на страни­ це. Роль состояния представления рассматривается в главе 34. Для получения более ясного вывода можно разнести текстовые данные по уникаль­ но именованным элементам (newTextBoxO, newTextBoxl и newTextBox2). Рассмотрим следующую модификацию: protected void btnGetTextData_Click(object sender, System.EventArgs e) { // Получить текстовые поля по имени. string lableData = string.Format ("<li> {0 }</lixbr/>" , Request.Form.Get("newTextBoxO")); lableData += string.Format("<li>{0}</li><br/>", Request.Form.G e t ("newTextBoxl")); lableData += string.Format ("<li> {0 }</lixbr/>" , Request.Form.Ge t ("newTextBox2")); lblTextBoxData.Text = lableData; } Используя этот подход, вы заметите, что как только запрос обработан, текстовое поле исчезнет. Причина этого кроется в не поддерживающей состояние природе HTML. Чтобы сохранять эти динамически созданные TextBox между обратными отправками, нужно пользоваться приемами программирования состояния ASP.NET (см. главу 34). Исходный код. Веб-сайт DynamicCtrls доступен в подкаталоге Chapter 33. Функциональность базового класса WebControl Как видите, тип Control имеет ряд характеристик поведения, не связанных с графи­ ческим пользовательским интерфейсом (коллекцию элементов управления, поддержка автоматической обратной отправки и т.д.). С другой стороны, базовый класс WebControl предоставляет графический полиморфный интерфейс всем виджетам (некоторые свой­ ства WebControl перечислены в табл. 33.2). ‘ Почти все эти свойства очевидны, поэтому вместо того, чтобы рассматривать их использование по одиночке, давайте посмотрим на работу сразу множества элементов Web Forms. Глава 33. Веб-элементы управления, мастер-страницы и темы ASP.NET 1 265 Таблица 33.2. Избранные свойства базового класса W e b C o n tro l Свойство Назначение BackColor Получает или устанавливает цвет фона для веб-элемента управления BorderColor Получает или устанавливает цвет контура веб-элемента управления BorderStyle Получает или устанавливает стиль контура веб-элемента управления BorderWidth Получает или устанавливает ширину контура веб-элемента управления Enabled Получает или устанавливает значение, указывающее на то, что веб-элемент управления доступен CssClass Позволяет назначить виджету класс, определенный в каскадной таблице стилей Font Получает информацию о шрифте веб-элемента управления ForeColor Получает или устанавливает цвет переднего плана (обычно цвет текста) веб-элемента управления Height, Width Получает или устанавливает высоту и ширину веб-элемента управления Tablndex Получает или устанавливает индекс обхода по клавише <ТаЬ> веб-элемен­ та управления ToolTip Получает или устанавливает всплывающую подсказку веб-элемента управ­ ления, появляющуюся при наведении на элемент курсора мыши Основные категории веб-элементов управления ASP.NET Веб-элементы управления ASP. NETT можно разделить на несколько обширных катего­ рий, и все они видны в панели инструментов (Toolbox) Visual Studio 2010 (предполагается, что в визуальном конструкторе открыта страница *.aspx), как показано на рис. 33.3. В разделе Standard (Стандартные) панели инструментов находятся наиболее часто используемые элементы управления, включая Button, Label, TextBox и ListBox. В до­ полнение к этим замечательным элементам пользовательского интерфейса в разделе Standard также доступны и более экзотические веб-элементы управления, такие как Calendar, Wizard и AdRotator (рис. 33.4). Toolbox ^ □ X Toolbox Standard л Data Standard ч Validation Navigation AdPotator в BulletedList Login Button WebParts Calendar AJAX Extensions 0 IF TS Dynam ic Data Reporting H TM L л Pointer д % General CheckBox CheckBoxList DropDcwnList FileUpload HiddenField \ There are no usable controls in this group. Drag an item onto J this text to add it to the to olb ox / Рис. 33.3. Категории веб-элементов управления ASP.NET HyperLink Image Toolbox V Server Explorer Рис. 33.4. Веб-элементы управле­ ния ASP.NET из раздела Standard 1 2 6 6 Часть VII. Построение веб-приложений с использованием ASP.NET Раздел D ata (Данные) — это место, где можно найти набор элементов управления, используемых для операций привязки данных, включая новый элемент управления ASP.NET Chart, который позволяет визуализировать графики (круговые диаграммы, гистограммы и т.п.), обычно как результат операции привязки (рис. 33.5). Элементы управления проверкой достоверности (находящиеся в области Validation (Проверка достоверности) панели инструментов) очень интересны в том плане, что их можно конфигурировать для генерации блоков кода JavaScript клиентской стороны, ко­ торые проверяют входные поля на предмет корректности данных. Если случится ошиб­ ка проверки достоверности, пользователь увидит сообщение об ошибке и не сможет вы­ полнить обратную отправку на сервер, пока не исправит ошибку. Раздел Navigation (Навигация) панели Toolbox — место, где находится небольшой на­ бор элементов управления (Menu, SiteMapPath и TreeView), которые обычно работа­ ют в сочетании с файлом *. sitemap. Как уже кратко упоминалось ранее в этой главе, элементы управления навигацией позволяют описывать структуру многостраничного сайта, используя дескрипторы XML. По-настоящему экзотическим набором веб-элементов управления ASP.NETT можно назвать элементы из раздела Login (Вход), показанные на рис. 33.6. ГтЪЫЬох I л ▼ □ X - □ X Toolbox Standard Standard Data Data Validation Pointer > AtcessDataSource У Chart .;о DataList !р DetailsView Navigation Ъ * Login * Р CreateUserWizard LcginName FcrmViev/ *U) LoginStatus LcginView LinqDataSource 1KtYiem___________________ % Server Explorer LI Login EntityDataSource GndView -I Pointer ChangePassword DataPager < - - Рис. 33.5. Веб-элементы управления ASP.NET, ориентированные на данные PasswordRecovery a jt Server Explore. Рис. 33.6. Веб-элементы управления ASP.NET, связанные с безопасностью Эти элементы могут радикально упростить включение в веб-приложения базовых средств безопасности (восстановление пароля, экраны входа и т.п.). Фактически эти элементы управления настолько мощны, что даже динамически создают выделенную базу данных для хранения регистрационных данных (в папке App Data веб-сайта), если нет специфической базы данных для безопасности. На заметку! Остальные категории веб-элементов управления, представленные в панели инстру­ ментов Visual Studio (W ebParts (Веб-части), A JA X Extensions (Расширения AJAX) и Dynam ic Data (Динамические данные)), предназначены для решения более специфичных задач про­ граммирования и здесь не рассматриваются. Краткая информация о S y s t e m . W e b . U l . H t m l C o n t r o l s В действительности, в ASP.NETT поставляются два разных набора инструментов ве­ б-элементов управления. В дополнение к веб-элементам управления ASP.NETT (внутри пространства имен System.Web.Ul.HtmlControls) библиотеки базовых классов также предлагают элементы управления HTML. Глава 33. Веб-элементы управления, мастер-страницы и темы ASP.NET 1 2 67 Элементы управления HTML — это коллекция типов, позволяющих использовать традиционные элементы управления HTML на странице веб-формы. Однако в отли­ чие от простых HTML-дескрипторов, эти элементы являются объектно-ориентирован­ ными сущностями, которые могут быть сконфигурированы для запуска на сервере и потому поддерживают обработку событий серверной стороны. В отличие от веб-эле­ ментов управления ASP.NET, элементы HTML довольно просты по своей природе и пред­ лагают незначительную функциональность сверх стандартных HTML-дескрипторов (HtmlButton, HtmllnputControl, HtmlTable и т.д.). Элементы управления HTML могут быть удобны, если команда четко разделена на тех, кто строит пользовательский интерфейс HTML, и разработчиков .NET. Специалисты по HTML могут пользоваться своим веб-редактором, имея дело со знакомыми дескрип­ торами разметки и передавая готовые HTML-файлы команде разработки. После этого разработчики .NET могут конфигурировать эти элементы управления HTML для выпол­ нения в качестве серверных элементов управления (щелкая правой кнопкой мыши на элементе управления HTML в Visual Studio 2010). Это позволит разработчикам обраба­ тывать события серверной стороны и программно работать с виджетами HTML. Элементы управления HTML предоставляют общедоступный интерфейс, который имитирует стандартные атрибуты HTML. Например, для получения информации из об­ ласти ввода используется свойство Value вместо принятого у веб-элементов свойства Text. Учитывая, что элементы управления HTML не столь богато оснащены, как веб­ элементы управления ASP. NETT, далее в этой книге они не рассматриваются. Документация по веб-элементам управления На протяжении оставшейся части книги у вас будет шанс поработать с множест­ вом веб-элементов управления ASP.NET; однако вы определенно должны найти время, чтобы ознакомиться со сведениями о пространстве имен System.Web.Ul.WebControls в документации .NET Framework 4.0 SDK. Там вы найдете объяснения и примеры кода для каждого члена пространства имен (рис. 33.7). S f s t e m W f M ILW ebControk N am espace A c c e s s D a ta S o u rc e G a s s A c c e rs D a ta S rn jrc e V ie w G a r s A d C re a te d E v e n tA rg s Class A d C r e a te d E v e n tH a n d le r D e le g a te A d R o ta te i C lass A s s o c ia te d C e n tr o lC e n v erter C lass A u th e n tic a te E v e n tA r g s Class A u th e n t ic a te tv e n tH a n d le r D e le g a te A u t o C c m p le te T y p e E n u m e ra tio n A u to G e n e ra te d f-ie ld C lass A u to G e n e r a te d F ie ld P r c p e rtie s Class B a s e C o m p a r e V a lid a tc r Class B a s e D a ta B o c m d C o n tro l C lass E as e D ataL is t Class B a s e V a lid a to r Class B o rd e rS ty le E iu im e r a t ic r B o u n d C o lu m n Class B c u n d F ie ld Class E u lle te d L is t Class B u lle te d L is tD is p la y M o d e E n u m e r a tio n B u lle te d L is tE v e n tA rg s Class B ulleted !istE w e n tH a n d le r D e le g a te B u lle tS ty le E n u m e r a tio n B u tto n Class B u tto n C o lu m n Class B u tto n C o lu m n T y p e E n u m e ra tio n ButtonField G ass_______________________ Рис. 33.7. Все веб-элементы управления ASP.NET описаны в документации .NET Framework 4.0 SDK 1 2 6 8 Часть VII. Построение веб-приложений с использованием ASP.NET Построение веб-сайта ASP.NET Cars Учитывая, что очень много “простых” элементов управления выглядят и ведут себя подобно своим аналогам из Windows Forms, детали базовых виджетов (Button, Label, TextBox и т.д.) подробно рассматриваться не будут. Вместо этого давайте построим веб-сайт, в котором иллюстрируется работа с некоторыми из наиболее экзотичных эле­ ментов управления, а также моделью мастер-страницы ASP.NET и особенностями меха­ низма привязки данных. В частности, в приведенном ниже примере будут продемонст­ рированы следующие приемы: • работа с мастер-страницами; • работа с навигацией посредством карты сайта; • работа с элементом управления GridView; • работа с элементом управления Wizard. Для начала создайте проект Empty Web Site по имени AppNetCarsSite. Обратите внимание, что мы пока не создаем новый проект ASP.NET Web Site, поскольку в нем до­ бавляется множество начальных файлов, которые пока еще не рассматривались. В дан­ ном проекте все необходимое будет добавляться вручную. Работа с мастер-страницами Многие веб-сайты обеспечивают согласованный внешний вид и поведение, распро­ страняющийся на множество страниц (общая система навигации с помощью меню, общее содержимое заголовков и нижних колонтитулов, логотип компании и т.п.). В ASP.NET 1.x разработчики интенсивно использовали элементы UserControl и специ­ альные веб-элементы управления для определения веб-содержимого, которое присутст­ вовало на многих страницах. Хотя UserControls и специальные веб-элементы управ­ ления по-прежнему работают в ASP.NET, также имеется концепция мастер-страниц, которая дополняет существующие технологии. Просто говоря, мастер-страница — это всего лиш ь страница ASP.NET, имеющая расширение файла *. mas ter. Сами по себе мастер-страницы не видимы в браузере клиентской стороны (фактически, исполняющая среда ASP.NET не обслуживает веб-со­ держимое такого рода). Вместо этого мастер-страницы определяют общую компоновку пользовательского интерфейса, разделяемую всеми страницами (или их подмножест­ вом) сайта. Кроме того, страница *. mas ter определяет различные области-заполнители содер­ жимого, которые устанавливают область пользовательского интерфейса, куда могут подключаться другие файлы *.aspx. Как будет показано, файлы *.aspx, которые вклю­ чают свое содержимое в мастер-страницу, выглядят и ведут себя немного иначе, чем те файлы *.aspx, которые рассматривались до сих пор. В частности, файлы *.aspx этого типа называются страницами содержимого (content page). Страницы содержимого — это файлы *.aspx, в которых не определен HTML-элемент <form> (это работа мастер­ страницы). Однако с точки зрения конечного пользователя запрос осуществляется к заданно­ му файлу *.aspx. На веб-сервере соответствующие файлы * . master и *.aspx смеши­ ваются вместе — в единое объявление унифицированной HTML-страницы. Чтобы про­ иллюстрировать использование мастер-страниц и страниц содержимого, начните со вставки новой мастер-страницы в веб-сайт через пункт меню W ebsite^ A dd New Item (Веб-сайт1 ^ Добавить новый элемент); на рис. 33.8 показано результирующее диалоговое окно. Глава 33. Веб-элементы управления, мастер-страницы и темы ASP.NET 12 69 Рис. 33.8. Вставка нового файла *.master Начальная разметка файла MasterPage.master выглядит следующим образом: <%@ Master Language="C#" AutoEventWireup="true" CodeFile="MasterPage.master.cs" Inherits="MasterPage" %> < 1DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtmll/DTD/xhtmll-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Untitled Page</title> <asp:ContentPlaceHolder id="head" runat="server"> </asp:ContentPlaceHolder> </head> <body> <form id="forml" runat="server"> <div> <asp:ContentPlaceHolder id="ContentPlaceHolderl" runat="server"> </asp:ContentPlaceHolder> </div> </form> </body> </html> Первое, что здесь представляет интерес — новая директива <?d@Mastern o>. В основном эта директива поддерживает те же атрибуты, что и директива <u@Pagen u>, описанная в предыдущей главе. Подобно типам Раде, мастер-страница наследуется от определенно­ го базового класса, которым в данном случае является MasterPage. Открыв соответст­ вующий файл кода, вы увидите там следующее определение класса: public partial class MasterPage : System.Web.U I .MasterPage { protected void Page_Load(object sender, EventArgs e) } Другим интересным моментом в разметке мастер-страницы является определение <asp:ContentPlaceHolder>. В эту область мастер-страницы подключаются видже­ ты пользовательского интерфейса связанного файла содержимого *.aspx, а не содер­ жимое, определенное самой мастер-страницей. Если вы намерены подключить файл *.aspx к этой области, контекст внутри дескрипторов <asp:ContentPlaceHolder> и 1 2 70 Часть VII. Построение веб-приложений с использованием ASP.NET </asp:ContentPlaceHolder> обычно оставляется пустым. Тем не менее, эту область можно заполнить разнообразными веб-элементами управления, которые функцио­ нируют как пользовательский интерфейс по умолчанию, если заданный файл *.aspx не предоставит специфическое содержимое. Для данного примера предположим, что каждая страница *.aspx сайта имеет специальное содержимое, и потому элементы <asp:ContentPlaceHolder> будут пустыми. На заметку! В странице *. mas ter может быть определено произвольное количество заполните­ лей содержимого. К тому же отдельная страница *. mas ter может иметь вложенные страницы *.master. Общий интерфейс файла *. mas ter можно строить с помощью тех же визуальных кон­ структоров Visual Studio 2010, которые используются для создания файлов *.aspx. Для данного сайта будет добавлен описательный элемент Label (служащий в качестве общего приветственного сообщения), элемент управления AdRotator (случайно показывающий одно из двух изображений) и элемент управления TreeView (позволяющий пользователю выполнять навигацию на другие области сайта). Ниже показана возможная разметка. <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Untitled Page</title> <asp:ContentPlaceHolder id="head" runat="server"> </asp:ContentPlaceHolder> </head> <body> <form id="forml" runat="server"> <div> <hr /> <asp:Label ID="Labell" runat="server" Font-Size="XX-Large" Text="Welcome to the ASP.NET Cars Super Site 1 "></asp:Label> <asp:AdRotator ID="myAdRotator" runat="server"/> &nbsp;<br /> <br /> <asp:TreeView ID="navigationTree" runat="server"> </asp:TreeView> <hr /> </div> <div> <asp:ContentPlaceHolder id="ContentPlaceHolderl" runat="server"> </asp:ContentPlaceHolder> </div> </form> </body> </html> На рис. 33.9 показано представление текущей мастер-страницы во время проекти­ рования. Внешний вид элемента управления TreeView можно улучшить, используя встроен­ ный редактор элемента управления и выбрав ссылку Auto Format... (Автоформат). В рас­ сматриваемом примере в результирующем диалоговом окне выбрана тема Arrow, в ре­ зультате чего для этого элемента управления получена следующая разметка: <asp:TreeView ID="navigationTree" runat="server" ImageSet="Arrows"> <HoverNodeStyle Font-Underline="True" ForeColor="#5555DD" /> <NodeStyle Font-Names="Verdana" Font-Size="8 pt" ForeColor="Black" HorizontalPadding="5px" NodeSpacing="Opx" VerticalPadding="Opx" /> Глава 33. Веб-элементы управления, мастер-страницы и темы ASP.NET 1271 <ParentNodeStyle Font-Bold="False" /> <SelectedNodeStyle Font-Underline="True" ForeColor="#5555DD" HorizontalPadding="Opx" VerticalPadding="Opx" /> </asp:TreeView> M«*crP.Ki* m « ter Welcome to the ASP.NET Cars Super Sitelis e Root b P a re n t 1 Leaf 1 L eaf 2 fo P a re n t 2 L eaf 1 L eaf 2 ir~~~~ r — :------------— ------- — Л Design — .......... ::— — —и □ Sptrt j Й Soofce Рис. 33.9. Разделяемый пользовательский интерфейс файла *.master Работа с логикой навигации по сайту с помощью элемента управления T r e e V ie w ASP.NETT поставляется с несколькими веб-элементами управления, поддерживающи­ ми навигацию по сайту: SiteMapPath, TreeView*и Menu. Эти веб-виджеты могут быть сконфигурированы различными способами. Например, каждый из этих элементов управления может динамически генерировать свои узлы с применением внешнего XMLфайла (или файла * . sitemap на основе XML), программно в коде или через разметку с использованием визуальных конструкторов среды Visual Studio 2010. Создаваемая система навигации будет динамически наполняться через файл *. sitemap. Преимущество такого подхода состоит в том, что можно определить общую структуру веб-сайта во внешнем файле и затем привязать его к элементу управления TreeView (или Menu) на лету. Таким образом, если навигационная структура веб-сайта изменится, доста­ точно будет просто модифицировать файл *. sitemap и перегрузить страницу. Для начала вставьте новый файл Web.sitemap в проект, выбрав пункт меню Website^Add New Item, в результате чего откроется диалоговое окно, показанное на рис. 33.10. Рис. 33.10. Вставка нового файла Web.sitemap 1 2 72 Часть VII. Построение веб-приложений с использованием ASP.NET Как видите, файл Web.sitemap определяет элемент самого верхнего уровня с двумя подузлами: <?xml version="1.О" encoding="utf-8" ?> <siteMap xmlns="http://schemas.miегоsoft.com/AspNet/SiteMap-File-1.0" > <siteMapNode url="" title="" description^'"> <siteMapNode url="" title="" descnption="" /> <siteMapNode url="" title="" description="" /> </siteMapNode> </siteMap> Если привязать эту структуру к элементу управления Menu, отобразится меню верх­ него уровня с двумя подменю. Таким образом, когда вы захотите определить подме­ ню, просто определите новые элементы <siteMapNode> в контексте существующего <siteMapNode>. В любом случае цель состоит в определении общей структуры веб-сайта в файле Web.sitemap с использованием множества элементов <siteMapNode>. Каждый из этих элементов может определять атрибуты заголовка и URL. Атрибут URL представ­ ляет файл *. aspx для навигации, когда пользователь щелкнет на заданном пункте меню (или на узле TreeView). Карта сайта содержит три узла (ниже узда верхнего уровня кар­ ты сайта): • Н о т е (Домой): Default .aspx • Build а Саг (Собрать автомобиль): BuildCar. aspx • View Inventory (Просмотреть склад): Inventory, aspx Система меню имеет единственный элемент верхнего уровня W elcom e (Добро пожа­ ловать) с тремя подэлементами. Модифицируем файл Web. sitemap следующим образом (имейте в виду, что каждое значение url должно быть уникальным; в противном случае возникнет ошибка времени выполнения). <?xml version="1.0" encoding="utf-8" ?> <siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" > <siteMapNode url="" title="Welcome !" descnption=""> <siteMapNode url="~/Default.aspx" title="Home" descnption="The Home Page" /> <siteMapNode url="~/BuildCar.aspx" title="Build a car" descnption="Create your dream car" /> <siteMapNode url="~/Inventory.aspx" title="View Inventory" description="See what is in stock" /> </siteMapNode> </siteMap> На заметку! Префикс ~/ перед каждой страницей в атрибуте url представляет собой нотацию, указывающую на корень веб-сайта. Теперь, несмотря на то, что можно было подумать, файл Web.sitemap не ассоции­ руется непосредственно с элементами Menu или TreeView, используя заданное свой­ ство. Вместо этого файл *. mas ter или *.aspx, содержащий виджет пользовательско­ го интерфейса, который отобразит файл Web.sitemap, должен содержать компонент SiteMapDataSource. Этот тип автоматически загрузит файл Web.sitemap в свою объ­ ектную модель при запросе страницы. Типы Menu и TreeView затем установят свои свойства DataSourcelD так, чтобы они указывали на экземпляр SiteMapDataSource. Для добавления нового SiteMapDataSource в файл * . master и автоматической ус­ тановки свойства DataSourcelD можно использовать визуальный конструктор Visual Studio 2010. Откройте встроенный редактор элемента управления TreeView (щелкнув на небольшой стрелке в правом верхнем углу элемента TreeView) и выберите пункт <New Data S o u rc e ...> (Новый источник данных), как показано на рис. 33.11. Глава 33. Веб-элементы управления, мастер-страницы и темы ASP.NET 1 273 M a s te rP a g e -m a s te r* X | Welcome to the ASP.NET Cars Super Site!* as£: TreeV wev. % enul J Roof Ш - Parent 1 Leal 1 Leaf 2 ■ Panin 2 Leaf 1 leaf 2 -* Design "Э Split TreeVww Tasks A u t o F o r m a t ... C h o o s e D a ta S o u rc e: Ed«t N o d e s .. ‘j (N o n e ) I (N o n e ) S h o w L in e s ea Source I [». htrrTT[ [T b o d y > 11< fo rm n fo rm 2 > | J <asp TreeVi«wc M e n u l > jTj Рис. 33.11. Добавление нового источника SiteMapDataSource В результирующем диалоговом окне выберите значок SiteMap (Карта сайта). В ре­ зультате будет установлено свойство DataSourcelD элемента Menu, а также к страни­ це добавится компонент SiteMapDataSource. Это все, что понадобится сделать, чтобы сконфигурировать элемент управления TreeView для перехода на дополнительные стра­ ницы сайта. Если необходимо выполнить дополнительную обработку при выборе поль­ зователем пункта меню, это можно сделать, обработав событие SelectedNodeChanged. В рассматриваемом примере в этом нет необходимости, но имейте в виду, что можно определить, какой пункт меню был выбран, используя входные аргументы, связанные с событием. Установка навигационных цепочек с помощью типа Прежде чем перейти к элементу управления AddRotator, добавьте тип SiteMapPath (расположенный на вкладке Navigation (Навигация) панели инструментов) в файл *.master ниже элемента-заполнителя содержимого. Этот виджет автоматически на­ страивает свое содержимое на основе текущего выбора системы меню. Как вам, воз­ можно, известно, это может предоставить полезную визуальную подсказку конечному пользователю (формально эта техника пользовательского интерфейса называется на вигационными цепочками или “хлебными крошками" (breadcrumbs)). По завершении вы заметите, что при выборе пункта меню W elcom ed Build а Саг (Добро пожаловать1 ^ Собрать автомобиль) виджет SiteMapPath автоматически обновится. Работа с элементом A d d R o t a t o r Назначение виджета ASP.NET AdRotator заключается в показе случайно выбран­ ного изображения в одной и той же позиции браузера. Поместите виджет AdRotator на поверхность визуального конструктора. Он отображается как пустой заполнитель. Функционально этот элемент управления не может выполнять свою работу до тех пор, пока в его свойстве AdvertisementFile не будет указан исходный файл, описывающий каждое изображение. Для данного примера источником данных будет простой XMLфайл по имени Ads.xml. Чтобы добавить XML-файл к веб-сайту, выберите пункт меню W ebsite^Add New Item (Веб-сайт1 ^ Добавить новый элемент) и укажите опцию XML file (XML-файл). Назовите его Ads .xml и предусмотрите уникальный элемент <Ad> для каждого изображения, которое планируется показывать. Как минимум, в элементе <Ad> должно быть указано графиче­ ское изображение для показа (ImageUrl), URL для навигации, если изображение выбра­ но (TargetUrl), альтернативный текст (AlternateText) и вес показа (Impressions): 1 2 7 4 Часть VII. Построение веб-приложений с использованием ASP.NET <Advertisements> <Ad> <ImageUrl>SlugBug.jpg</ImageUrl> <TargetUrl>http://www.Cars.com</TargetUrl> <AlternateText>Your new Car?</AlternateText> <Impressions>80</Impressions> </Ad> <Ad> <ImageUrl>car.gif</ImageUrl> <TargetUrl>http://www.CarSuperSite.com</TargetUrl> <AlternateText>Like this Car?</AlternateText> <Impressions>80</Impressions> </Ad> </Advertisements> Здесь указаны два файла с изображениями (car.gif и slugbug.jpg). В результате необходимо обеспечить наличие этих файлов в корне веб-сайта (эти файлы включены в состав кода примеров для этой книги). Чтобы добавить их к текущему проекту, выбери­ те пункт меню Web S ite ■=>Add Existing Item (Веб-сайт1 ^ Добавить существующий элемент). В этот момент можно ассоциировать XML-файл с элементом управления AdRotator че­ рез свойство Advertisement File (в окне Properties): <asp.-AdRotator ID="myAdRotator" runat="server" AdvertisementFile="~/Ads.xml"/> Позднее, когда вы запустите приложение и выполните обратную отправку страницы, то получите случайно выбранный из двух файлов изображения. Определение страницы содержимого D e fa u lt.a s p x Теперь, имея готовую мастер-страницу, можно приступить к проектированию инди­ видуальных страниц *.aspx, которые определят содержимое пользовательского интер­ фейса для вставки в дескриптор <asp:ContentPlaceHolder> мастер-страницы. Файлы *.aspx, которые объединяются с мастер-страницей, называются страницами содержи­ мого (content page) и имеют несколько ключевых отличий от нормальной, автономной веб-страницы ASP.NETT. В своей основе файл *. mas ter определяет раздел <form> финальной HTML-страницы. Поэтому существующая область <form> внутри файла *.aspx должна быть заменена контекстом <asp:Content>. Поскольку можно вручную модифицировать разметку в на­ чальном файле *.aspx, можно добавить к проекту новую страницу содержимого; щелк­ ните правой кнопкой мыши в любом месте на поверхности визуального конструктора файла * . master и выберите в контекстном меню пункт Add Content Раде (Добавить страницу содержимого). В результате будет сгенерирован новый файл *.aspx со сле­ дующей начальной разметкой: <%@ Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" Title="Untitled Page" %> <asp:Content ID="Contentl" ContentPlaceholderID="head" Runat="Server"> </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolderl" Runat="Server"> </asp:Content> Первым делом, обратите внимание на то, что директива <%@Раде%> дополнена новым атрибутом MasterPageFile, который указывает на файл * . master. Кроме того, вместо элемента <form> имеется контекст <asp:Content> (пока пустой), в котором значение Глава 33. Веб-элементы управления, мастер-страницы и темы ASP NET 1275 C o n t e n t P l a c e H o l d e r l D установлено идентично компоненту < a s p : C o n t e n t P l a c e H o l d e r > в файле мастер-страницы. Имея эти ассоциации, страница содержимого знает, куда следует подключить ее со­ держимое, в то время как содержимое мастер-страницы отображается как предназначен­ ное только для Чтения на странице содержимого. Нет необходимости в построении слож­ ного пользовательского интерфейса для области содержимого D e f a u l t .aspx. Для данного примера просто добавьте некоторый литеральный текст с базовыми инструкциями по сайгу, как показано на рис. 33.12 (обратите внимание, что в правом верхнем углу стра­ ницы содержимого находится ссылка для переключения к связанной мастер-странице). D e fa u lt aspx* X | Master F ag4 .mask г Object Ь/'-wsr i C lie n t O b je c ts & Events <tt P a g e (No Events) anguage»"C*” <asp:Content . s t e r ^ a g e F i L e » " ~ / M a s t e r P a g e . m a s t e r " Autot ■- n t t o r e j p = " t r u e " ; 0 - “C o n t e n t l ‘ iodpF i "Default. ^ rntentPlBceHclderID«"head“ R u n a t »"Server"> </asp:Content> <asn:Content - intentPjacr+tolderlD*" C o n t e n t P l a c e H o l d e r l " ii>«"Content2' R u n a t * “S e r v e r ” > <p> H e r e y o u can p u r c h a s e a n e w c a r or b u i l d y o u r dream W e l c o m e t o o u r si t e . & n b car. s/p> M a s te rP a g e .r .is te r t> B u ild a c a r l> V t e * I n v e n t o r y S»teMapD*U5ourc e S u te M a p D a ta S o u rc e l C o n te o tP la c e H o ld e i 1 [C iis to m > l£ l____________ ________________________________________________________ [W e lc o m e to o ur site H ere you can purchase a n e w car o r build your dream c ar Root Wa4t i P » « » t K ' - i . ■ Л D e s ig n jn S p lit Currant Nod* a i S o u rc e [Ij|< a s p .C o n te n fC o n te n t2 > [ < p > Рис. 33.12. Создание первой страницы содержимого Теперь, после запуска проекта вы увидите, что содержимое пользовательского ин­ терфейса файлов * . m a s t e r и D e f a u l t . a s p x слиты в единый поток HTML. Как показано на рис. 33.13, конечный пользователь понятия не имеет о существовании мастер-стра­ ницы. Кроме того, если обновить страницу (нажав <F5>), элемент A d R o t a t o r покажет случайно выбранное одно из двух изображений. С Л Ф http localhost ШЗ/AspNetCarsSite/Defailltasp* ► Welcome to the ASP.NET Cars Super Site! Want a RED slug bug? Come to CarSuperSite.com ▼ W e lc o m e ' t> H o m e t> B u ild a c a r t> V ie w In v e n t o r y W e lco m e to our site W e lc o n m t H ere v ou can purchase a new car or build vour dream car H om e Рис. 33.13. Во время выполнения мастер-страницы и страницы содержимого визуализируются в единую форму 1 2 76 Часть VII. Построение веб-приложений с использованием ASP.NET На заметку! Имейте в виду, что мастер-страница объекта Раде может быть установлена про­ граммно в обработчике события Prelnit унаследованного от Раде типа с использованием унаследованного свойства Master. Проектирование страницы содержимого i n v e n t o r y , a s p x Чтобы вставить страницу содержимого Inventory, aspx в текущий проект, откройте страницу * . master в IDE-среде, выберите пункт меню W ebsite^ A dd Content Page (Веб­ сайт1 ^ Добавить страницу содержимого) и переименуйте этот файл в Inventory, aspx. Назначение этой страницы содержимого склада состоит в отображении содержимого таблицы Inventory базы данных AutoLot внутри элемента управления GridView. Элемент управления ASP.NETT GridView обладает способностью представлять в раз­ метке данные строки соединения и SQL-операторы Select, Insert, Update и Delete (или, альтернативно — хранимые процедуры). Поэтому вместо написания всего необхо­ димого кода ADO.NETT вручную, можно позволить классу SqlDataSource генерировать разметку автоматически. С помощью визуальных конструкторов можно присвоить свой­ ству DataSourcelD элемента GridView соответствующий компонент SqlDataSource. Выполнив несколько простых щелчков кнопкой мыши, можно настроить GridView на автоматическую выборку, обновление и удаление записей лежащего в основе хра­ нилища данных. Хотя образ мышления “нулевого кода” значительно сокращает общий объем кода, следует помнить, что эта простота оплачивается утерей контроля и не все­ гда может быть лучшим подходом для приложений масштаба предприятия. Эта модель может замечательно подойти для страниц с низким трафиком, прототипирования веб­ сайта или небольших домашних приложений. Чтобы проиллюстрировать работу с GridView (и логикой доступа к данным) в декла­ ративной манере, начните с обновления страницы содержимого Inventory, aspx, доба­ вив элемент управления Label. Затем откройте инструмент Server Explorer (через меню View (Вид)) и удостоверьтесь, что добавили соединение с данными из базы AutoLot, соз­ данной ранее при изучении ADO.NETT (процесс создания соединения с данными описан в главе 21). Теперь выберите таблицу Inventory и перетащите ее на область содержи­ мого файла Inventory, aspx. В ответ на эти действия IDE-среда выполнит следующие шаги. 1. Файл Web.config будет дополнен новым элементом <connectionStrings>. 2. Компонент SqlDataSource будет сконфигурирован необходимой логикой Select, Insert, Update и Delete. 3. Свойство DataSourcelD элемента GridView будет установлено в компонент SqlDataSource. На заметку! В качестве альтернативы конфигурировать виджет GridView можно с помощью встро­ енного редактора. Выберите <New Data Source> в раскрывающемся списке C h o o se Data S o u rce (Выберите источник данных). Это активизирует мастер, который проведет через после­ довательность шагов для подключения этого компонента к необходимому источнику данных. Если вы посмотрите на открывающее объявление элемента управления GridView, то увидите, что свойство DataSourcelD установлено в только что определенный компо­ нент SqlDataSource: <asp:GridView ID="GridViewl" runat="server" AutoGenerateColumns="False" DataKeyNames="CarID" DataSourceID="SqlDataSourcel" EmptyDataText="There are no data records to display."> <Columns> Глава 33. Веб-элементы управления, мастер-страницы и темы ASP.NET 1 2 77 <asp:BoundField DataField="CarID" HeaderText="CarID" ReadOnly="True" SortExpression="CarID" /> <asp:BoundField DataField="Make" HeaderText="Make" SortExpression="Make" /> <asp:BoundField DataField="Color" HeaderText="Color" SortExpression="Color" /> <asp:BoundField DataField="PetName" HeaderText="PetName" SortExpression="PetName" /> </Columns> </asp:GndView> Тип SqlDataSource — это место, где происходит большая часть всей деятельно­ сти. В приведенной ниже разметке обратите внимание, что этот тип записывает все необходимые операторы SQL (в виде параметризованных запросов) для взаимодей­ ствия с таблицей Inventory базы данных AutoLot. Кроме того, используя синтак­ сис $ свойства Connectionstring, этот компонент автоматически читает значение <connectionString> из Web.config: <asp:SqlDataSource ID="SqlDataSourcel" runat="server" ConnectionString="<%$ ConnectionStrings:AutoLotConnectionStringl %>" DeleteConunand=MDELETE FROM [Inventory] WHERE [CarlD] = @CarID" InsertCommand="INSERT INTO [Inventory] ([CarlD], [Make], [Color], [PetName]) VALUES (@CarID, @Make, @Color, @PetName)" ProviderName="<'u$ ConnectionStrings :AutoLotConnectionStringl .ProviderName n,>" SelectCommand="SELECT [CarlD], [Make], [Color], [PetName] FROM [Inventory]" UpdateCommand="UPDATE [Inventory] SET [Make] = @Make, [Color] = @Color, [PetName] = @PetName WHERE [CarlD] = @CarID"> <DeleteParameters> <asp:Parameter Name="CarID" Type="Int32" /> </DeleteParameters> <UpdateParameters> <asp:Parameter Name=’’Make" Type="Stnng" /> <asp:Parameter Name=’Color" Type="String" /> <asp:Parameter Name=’PetName" Type="Stnng" /> <asp:Parameter Name=’’CarlD" Type="Int32" /> </UpdateParameters> <InsertParameters> <asp:Parameter Name=’’CarlD" Type="Int32" /> <asp:Parameter Name= ’Make" Type="String" /> <asp:Parameter Name= ’Color" Type="Stnng" /> <asp:Parameter Name= ’PetName" Type="Stnng" /> </InsertParameters> </asp:SqlDataSource> Теперь можете запустить веб-приложение, выбрать пункт меню View Inventory (Просмотреть склад) и просмотреть данные, как показано на рис. 33.14. (Обратите вни­ мание, что элемент DataView имеет уникальный внешний вид, установленный с помо­ щью встроенного визуального конструктора). Включение сортировки и разбиения на страницы Элемент управления GridView можно легко настроить для выполнения сортировки (через гиперссылки имен столбцов) и разбиения на страницы (с помощью числовых ги­ перссылок или гиперссылок “следующая/предыдущая”). Для этого активизируйте встро­ енный редактор и отметьте соответствующие флажки, как показано на рис. 33.15. Теперь страница позволяет сортировать данные щелчками на именах столбцов и прокруткой данных через постраничные ссылки (разумеется, если в таблице Inventory присутствует достаточное количество записей). 1 2 7 8 Часть VII. Построение веб-приложений с использованием ASP.NET С Л Й htt; •/ .lo calh ost 112j/AspI4etCaTsSitey ► Q ’ Л 4" Welcome to the ASP.NET Cars Super Site! W ant a B lu e S L U G B U G ? Com e to Cars.com ! ▼ Welcome' > Home Build a car l> V iew In v e n t CarlD Make Color PetName 83 Ford Rust Rusty 107 Ford Red Snake 555 Ford Yellow Buzz 6^8 Yugo Green Clunker 904 VW Black 1000 BMW Black Bimmer 1001 BMW Tan Daisy 1992 Saab Pmkey 2222 Yugo Blue W elcom e! Pmk Hank View Inventory Рис. 33.14. Модель “нулевого кода” компонента SqlDataSource Рис. 33.15. Включение сортировки и разбиения на страницы Глава 33. Веб-элементы управления, мастер-страницы и темы ASP.NET 1279 Включение редактирования “на месте” Последнее, что еще можно сделать на этой странице — это включить поддержку ре­ дактирования “на месте” элемента управления GridView. Учитывая, что SqlDataSource уже имеет необходимую логику Delete и Update, все, что понадобится сделать — отме­ тить флажки Enable Deleting (Разрешить удаление) и Enable Editing (Разрешить редакти­ рование) элемента GridView (см. рис. 33.15). После этого на странице Inventory, aspx можно будет редактировать и удалять записи, как показано на рис. 33.16, обновляя л е ­ жащую в основе таблицу Inventory базы данных AutoLot. • — а ► D - X 1 А ’ I UnttciPage щ 1 <- С ti localhost J12:. A'-pNetCarsSit e/Inventoty.aspx Ф Welcome to the ASP.NET Cars Super Site! Want a RED slug bug? Come to CarSuperSite.com w W e lc o m e 1 t> H o m e t> B u ild a ca*t> V ie w In v e n t o r y Color Maks Edit Delete 83 Edrt Delete 555 Ford Rust ■ Snala I вмГ Ford EgL^saag Yellow | Buzz Edit Delete 6’ 8 Yugo Green Clunker Edit Delete 904 VW Black Hank Edit Delete 1000 BMW Black Впишет Edit Delete 1001 BMW Tan Daisy Edit Delete 1992 Saab Pink Pmkey Edit Delete 2222 Yugo Bhie Welcoinel j Rusty :View Inventory Рис. 33.16. Функциональность редактирования и удаления На заметку! Включение редактирования “на месте" для GridView требует наличия в таблице базы данных первичного ключа. Если активизировать эту опцию не удается, скорее всего, столбец CarlD не был установлен в качестве первичного ключа таблицы Inventory базы данных AutoLot. Проектирование страницы содержимого BuildCar.aspx В этом примере осталось еще спроектировать страницу содержимого BuildCar.aspx. Вставьте этот файл в текущий проект (с помощью пункта меню W e b site ^ A d d Content Раде). Эта новая страница использует веб-элемент управления ASP.NETT Wizard, кото­ рый обеспечивает простой способ для проведения конечного пользователя через после­ довательность взаимосвязанных шагов. Здесь эти шаги будут эмулировать акт сборки автомобиля для покупки. Поместите в область содержимого элементы управления Label и Wizard. Затем активизируйте встроенный редактор для Wizard и щелкните на ссылке A dd /R em o ve W izardSteps (Добавление и удаление шагов мастера). Добавьте четыре шага, как пока­ зано на рис. 33.17. 1 2 8 0 Часть VII. Построение веб-приложений с использованием ASP.NET Рис. 33.17. Конфигурирование элемента Wizard После определения этих шагов вы заметите, что Wizard предлагает пустую область содержимого, куда можно перетаскивать элементы управления для текущего выбран­ ного шага мастера. Для целей рассматриваемого примера модифицируем каждый шаг, добавив следующие элементы пользовательского интерфейса (не забудьте задать подхо­ дящие идентификаторы для каждого элемента в окне Properties): • P ick Your M odel (Выбор модели): элемент управления TextBox; • P ick Your C o lo r (Выбор цвета): элемент управления List Box; • Name Your Car (Название автомобиля): элемент управления TextBox; • D elivery Date (Дата доставки): элемент управления Calendar. Элемент управления List Box — единственный элемент пользовательского интер­ фейса внутри Wizard, который требует дополнительного шага. Выберите этот элемент в визуальном конструкторе (не забыв сначала выбрать ссылку Pick Your Color) и запол­ ните виджет набором цветов, используя свойство Items в окне Properties. После этого вы увидите в области определения Wizard разметку вроде следующей: <asp:ListBox ID="ListBoxColors" runat="server" Width="237px"> <asp:ListItem>Purple</asp:Listltem> <asp:ListItem>Green</asp:Listltem> - <asp:ListItem>Red</asp:Listltem> <asp:ListItem>Yellow</asp:Listltem> <asp:ListItem>Pea Soup Green</asp:ListItem> <asp:ListItem>Black</asp:ListItem> <asp:ListItem>Lime Green</asp:Listltem> </asp:ListBox> После определения шагов можно обработать событие FinishButtonClick для авто­ матически сгенерированной кнопки Finish (ГЬтово). Однако имейте в виду, что кнопка Finish не будет видна вплоть до завершающего шага мастера. Выбрав последний шаг, просто выполните двойной щелчок на кнопке Finish для генерации обработчика собы­ тий. Внутри этого обработчика событий серверной стороны извлеките выбор из каж­ дого элемента пользовательского интерфейса и постройте строку описания, которую присвойте свойству Text дополнительного элемента типа Label по имени lblOrder: Глава 33. Веб-элементы управления, мастер-страницы и темы ASP.NET 1281 public partial class Default2 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } . . protected void carWizard_FinishButtonClick(object sender, System.Web.UI.WebControls.WizardNavigationEventArgs e) { // Получить каждое значение. string order = string.Format("{0}, your {1} (2} will arrive on (3}.", txtCarPetName.Text, ListBoxColors.SelectedValue, txtCarModel.Text, carCalendar.SelectedDate .ToShortDateStnng () ); / / Присвоить реэультиружвдго строку метке. lblOrder.Text order; } } Веб-приложение AspNetCarsSite готово. На рис. 33.18 показан элемент Wizard в действии. На этом рассмотрение различных ASP. NETT веб-элементов управления пользователь­ ского интерфейса, мастер-страниц, страниц содержимого и навигации с помощью кар­ ты сайта завершено. Далее мы переходим к исследованию функциональности элемен­ тов управления проверкой достоверности ASP.NETT. Исходный код. Веб-сайт AspNetCarsSite доступен в подкаталоге Chapter 33. 1 2 82 Часть VII. Построение веб-приложений с использованием ASP.NET Роль элементов управления проверкой достоверности Следующий набор элементов управления Web Forms, который мы рассмотрим, извес­ тен под общим названием элементы управления проверкой достоверности (validation controls). В отличие от других элементов управления Web Fbrms, эти элементы не генери­ руют HTML-разметку для визуализации, а применяются для генерации JavaScript-кода клиентской стороны (и, возможно, связанного с ним кода серверной стороны) в целях проверю! достоверности данных формы. Как было показано в начале этой главы, провер­ ка достоверности данных формы клиентской стороны удобна тем, что позволяет на месте проверять данные на предмет соответствия различным ограничениям, прежде чем посы­ лать их обратно веб-серверу, тем самым сокращая дорогостоящий трафик. В табл. 33.3 дана краткая сводка по элементам управления проверкой достоверности ASP. NETT. Таблица 3 3.3. Элементы управления проверкой достоверности ASP.NET Элемент управления Назначение CompareValidator Проверяет значение в элементе ввода на равенство заданному значению другого элемента ввода или фиксированной константе CustomValidator Позволяет строить пользовательскую функцию проверки дос­ товерности, которая проверяет заданный элемент управления RangeValidator Определяет, находится ли данное значение в пределах пред­ варительно заданного диапазона RegularExpressionValidator Проверяет значение в ассоциированном элементе ввода на соответствие шаблону регулярного выражения RequiredFieldValidator Проверяет заданный элемент ввода на наличие значения (т.е. что он не пуст) ValidationSummary Отображает итог по всем ошибкам проверки достоверности страницы в формате простого списка, маркированного списка или одного абзаца. Ошибки могут отображаться встроенным способом и/или во всплывающем окне сообщения Все элементы управления проверкой достоверности в конечном итоге наследуются от одного общего базового класса по имени System.Web.UI.WebControls.BaseValidator и потому обладают набором общих средств. В табл. 33.4 документированы основные члены классов элементов управления проверкой достоверности. Таблица 33.4. Общие свойства элементов управления проверкой достоверности ASP.NET Член Назначение ControlToValidate Получает или устанавливает элемент управления, подлежащий про­ верке достоверности Display Получает или устанавливает поведение сообщений об ошибках в эле­ менте управления проверкой достоверности Enabled ient Script Получает или устанавливает значение, указывающее, включена ли проверка достоверности клиентской стороны ErrorMessage Получает или устанавливает текст для сообщения об ошибке ForeColor Получает или устанавливает цвет сообщения, отображаемого при не­ удачной проверке достоверности Глава 33. Веб-элементы управления, мастер-страницы и темы ASP.NET 1283 Чтобы проиллю стрировать работу с этими элем ентам и управления проверкой достоверности, создайте новый проект Em pty Web Site по имени ValidatorCtrls и вставьте в него новую веб-форму по имени Default.aspx. Для начала поместите на страницу четыре (именованных) элемента управления Text Box (с четырьмя соответ­ ствующими описательными элементами Label). Затем поместите на страницу рядом с каждым соответствующим полем элементы управления RequiredFieldValidator, RangeValidator, RegularExpressionValidator и CompareValidator. И, наконец, до­ бавьте элементы Button и Label (рис. 33.19). Рис. 33.19. Элементы управления проверкой достоверности обеспечат корректность данных формы перед обратной отправкой Теперь, имея начальный пользовательский интерфейс, рассмотрим процесс конфи­ гурирования каждого элемента управления проверкой достоверности. Класс R e q u i r e d F i e l d V a l i d a t o r Конфигурирование RequiredFieldValidator осуществляется просто. Для этого со­ ответствующим образом установите свойства ErrorMessage и ControlToValidate в Visual Studio 2010. Ниже показана результирующая разметка, которая обеспечивает проверку, что текстовое поле txtRequiredField не является пустым: <asp:RequiredFieldValidator ID="RequiredFieldValidatorl" runat="server" ControlToValidate="txtRequiredField" ErrorMessage="Oops1 Need to enter data."> </asp:RequiredFieldValidator> Класс RequiredFieldValidator поддерживает свойство InitialValue. Его можно применять для проверки того, что пользователь ввел в связанном элементе TextBox какое-то значение, отличное от начального. Например, когда пользователь впер­ вые получает страницу, можно сконфигурировать TextBox, чтобы он содержал зна­ чение “Please enter your name”. Если не установить свойство InitialValue элемента RequiredFieldValidator, исполняющая среда решит, что значение “Please enter your name” является допустимым. Таким образом, чтобы считать правильным в TextBox введенное значение, отличное от “Please enter your name”, настройте виджет, как пока­ зано ниже: 1 2 84 Часть VII. Построение веб-приложений с использованием ASP.NET <asp:RequiredFieldValidator ID="RequiredFieldValidatorl" runat="server" ControlToValidate="txtRequiredField" ErrorMessage="Oops! Need to enter data." InitialValue="Please enter your name"> </asp:RequiredFieldValidator> Класс R e g u l a r E x p r e s s i o n V a l i d a t o r Класс RegularExpressionValidator может использоваться, когда необходимо при­ менить шаблон к символам, вводимым в заданном поле. Например, чтобы гарантиро­ вать ввод в заданном поле Text Box корректного номера карточки социального страхо­ вания США, виджет можно определить следующим образом: <asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server" ControlToValidate="txtRegExp" ErrorMessage="Please enter a valid US SSN." V alid ation E xp ressio n="\d{3 } - \ d { 2 } - \ d { 4 }"> </asp:PegularExpressionValidator> Обратите внимание на то, как в RegularExpressionValidator определено свойство ValidationExpression. Если вы ранее не работали с регулярными выражениями, то все, что следует знать для целей рассматриваемого примера — это то, что они исполь­ зуются для проверки соответствия строки определенному шаблону. Здесь выражение "\d{ 3}~\d{2}—\d{4}" получает стандартный номер карточки социального страхования С Ш А в форме х х х -х х -х х х х (где х — десятичная цифра). Это конкретное регулярное выражение достаточно очевидно; однако предполо­ жим, что требуется проверить правильность телефонного номера, скажем, в Японии. Корректное выражение для этого случая выглядит намного сложнее: " (0\d{ 1,4} - 1\ (0\d{ 1,4 }\)?)?\d{ 1,4 }-\d{4}".Удобно то, что при выборе свойства ValidationExpression в окне Pro perties доступен предварительно определенный список распространенных ре­ гулярных выражений (по щелчку на кнопке со стрелкой вниз). Н а з а м е т к у ! За программные манипуляции регулярными выражениями в .NET отвеча­ ют два пространства имен — System.Text.RegularExpressions и System.Web. RegularExpressions. Класс R a n g e V a l i d a t o r В дополнение к свойствам MinimumValue и MaximumValue, в классе RangeValidator имеется свойство по имени Туре. Поскольку нужно проверять пользовательский ввод на предмет вхождения в диапазон целых чисел, следует указать тип Integer (это не является установкой по умолчанию): <asp:RangeValidator ID="RangeValidatorl" runat="server" ControlToValidate="txtRange" ErrorMessage="Please enter value between 0 and 100." MaximumValue="100" MinimumValue="0" Type="Integer"> </asp:RangeValidator> Класс RangeValidator также может использоваться для проверки вхождения в диа­ пазон денежных значений, дат, чисел с плавающей точкой и строковых данных (уста­ новка по умолчанию). К л асс C o m p a r e V a l i d a t o r Наконец, обратите внимание, что CompareValidator поддерживает свойство Operator: Глава 33. Веб-элементы управления, мастер-страницы и темы ASP.NET 1 285 <asp:CompareValidator ID="CompareValidatorl" runat="server" ControlToValidate="txtComparison" ErrorMessage="Enter a value less than 20." Operator="LessThan" ValueToCompare="20" Type="Integer"> </asp:CompareValidator> Учитывая, что предназначение элементов управления проверкой достоверности со­ стоит в сравнении значения в текстовом поле и другого значения с использованием бинарной операции, не удивительно, что свойство Operator может принимать такие значения, как LessThan, GreaterThan, Equal и NotEqual. В ValueToCompare указы­ вается значение, с которым нужно сравнивать. Обратите внимание, что атрибут Туре установлен в Integer. По умолчанию CompareValidator выполняет сравнения со стро­ ковыми значениями. На за м е тку ! Элемент CompareValidator также может быть настроен для сравнения со значе­ нием внутри другого элемента управления Web Forms (а не с жестко закодированной констан­ той) посредством свойства ControlToValidate. Чтобы завершить код этой страницы, обработайте событие Click элемента управле­ ния Button и информируйте пользователя об успешном прохождении логики проверки достоверности: public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } protected void btnPostback_Click(object sender, EventArgs e) { lblValidationComplete.Text = "You passed validation!"; } } Загрузите готовую страницу в браузер. Сначала вы не увидите каких-либо заметных изменений. Однако при попытке щелкнуть на кнопке Submit (Отправить) после ввода неверных данных появится сообщение об ошибке. После ввода правильных данных со­ общение об ошибке исчезнет и произойдет обратная отправка. Взглянув на HTML-разметку, визуализированную браузером, вы обнаружите, что элементы управления проверкой достоверности генерируют JavaScript-функцию кли­ ентской стороны, которая использует специфическую библиотеку функций JavaScript, автоматически загружаемую на пользовательскую машину. Как только проверка досто­ верности прошла, данные формы отправляются обратно на сервер, где исполняющая среда выполняет ту же самую проверку еще раз на веб-сервере (просто чтобы удосто­ вериться, что данные не были подделаны в пути). Кстати, если HTTP-запрос был прислан браузером, который не поддерживает JavaScript клиентской стороны, то вся проверка достоверности проходит на сервере. Таким образом, программировать элементы управления проверкой достоверности мож­ но, не задумываясь о целевом браузере; возвращенная HTML-страница переадресует об­ работку ошибок веб-серверу. Создание итоговой панели проверки достоверности Следующая тема, касающаяся проверки достоверности, которую мы рассмотрим здесь — применение виджета ValidationSummary. В данный момент каждый элемент управления проверкой достоверности отображает свое сообщение об ошибке именно в том месте, куда он был помещен во время проектирования. Во многих случаях именно 1 2 86 Часть VII. Построение веб-приложений с использованием ASP.NET это и требуется. Однако в сложных формах с многочисленными виджетами ввода вари­ ант с засорением формы многочисленными надписями красного цвета может не устро­ ить. С помощью типа ValidationSummary можно заставить все типы проверки досто­ верности отображать свои сообщения об ошибках в определенном месте страницы. Первый шаг состоит в помещении ValidationSummary в файл *.aspx. Дополнительно можно установить свойство HeaderText этого типа вместе с DisplayMode, которое по умолчанию отобразит список всех сообщений об ошибках в виде маркированного списка. <asp:ValidationSummary id="ValidationSummaryl" runat="server" Width="353px" HeaderText="Here are the things you must correct."> </asp:ValidationSummary> Затем необходимо установить свойство Display в None для всех индивидуаль­ ных элементов управления проверкой достоверности (т.е. RequiredFieldValidator, RangeValidator и т.д.). Это гарантирует отсутствие дублированных сообщений об ошибках при каждой неудаче проверки достоверности (одно — в итоговой панели, а другое — в месте расположения элементы управления проверкой достоверности). На рис. 33.20 показана итоговая панель в действии. С Л Ф http;, local host i - ► 0» A ' F u n w ith A S P . N E T V a lid a to r s Required Field: Please enter your name Range 0 100: •5 Enter sour US SSN Andrew Troelsen Value < 20 999999999 ^Post back Here are the things vou must correct • Oops* N eed to enter daia • Please enter value between 0 and 100 • Please enter a • Enter vahd U S S S N a value less than 20 Рис. 33.20. Использование итоговой панели проверки достоверности И последнее: если вы вместо этого хотите отображать сообщения об ошибках в окне сообщений клиентской стороны, установите свойство ShowMessageBox элемента управ­ ления ValidationSummary в true, а свойство ShowSummary — в false. Определение групп проверки достоверности Можно также определять группы к которым относятся элементы управления про­ веркой достоверности. Это полезно, когда имеются области страницы, которые рабо­ тают как единое целое. Например, может существовать одна группа элементов управ­ Глава 33. Веб-элементы управления, мастер-страницы и темы ASP.NET 12 87 ления в объекте Panel, предназначенная для ввода пользователем адреса электронной почты, и другая группа в другом объекте P a n e l — для ввода информации о кредитной карте. С помощью групп можно конфигурировать каждый набор элементов управления для независимой проверки достоверности. Вставьте в текущий проект новую страницу по имени V a l i d a t i o n G r o u p s . a s p x , определяющую две Panel. Первый объект P a n e l будет содержать T e x t B o x для не­ которого пользовательского ввода (через R e q u i r e d F i e l d V a l i d a t o r ) , а второй объ­ ект P a n e l — для ввода номера карточки социального страхования СШ А (через R e g u l a r E x p r e s s i o n V a l i d a t o r ) . На рис. 33.21 показан возможный вариант пользова­ тельского интерфейса. Рис. 33.21. Эти объекты P a n e l независимо конфигурируют свои области ввода Чтобы обеспечить независимую проверку достоверности, просто включите элемент управления проверкой достоверности и проверяемый элемент управления в уникально именованную группу, используя свойство Valida t i o n G r o u p . В следующем примере раз­ метки обратите внимание, что применяемые здесь обработчики события C l i c k остаются, по сути, пустыми в файле кода и служат только для обратной отправки на веб-сервер: <form id="forml" runat="server"> <asp:Panel ID="Panell" runat="server" Height="83px" Width="296px"> <asp:TextBox ID="txtRequiredData" runat="server" ValidationGroup="FirstGroup"> </asp:TextBox> <asp:RequiredFieldValidator ID="RequiredFieldValidatorl" runat="server" ErrorMessage="*Required field1" ControlToValidate="txtRequiredData" ValidationGroup="Firs tGroup"> </asp:RequiredFieldValidator> <asp:Button ID="bntValidateRequired" runat="server" OnClick="bntValidateRequired_Click" Text="Validate" ValidationGroup="FirstGroup" /> </asp:Panel> <asp:Panel ID="Panel2" runat="server" Height="119px" Width="295px"> <asp:TextBox ID="txtSSN" runat="server" ValidationGroup="SecondGroup"> </asp:TextBox> <asp:RegularExpressionValidator ID="RegularExpressionValidatorl" runat="server" ControlToValidate="txtSSN" ErrorMessage="*Need SSN" ValidationExpression="\d{ 3 }--\d{2 }--\d{ 4 }" ValidationGroup="SecondGroup"> </asp:RegularExpressionValidator>&nbsp; 1288 Часть VII. Построение веб-приложений с использованием ASP.NET <asp:Button ID=”btnValidateSSN” runat=”server” OnCllck=,,btnValldateSSN_Cllck,, Text=”Validate” ValidationGroup=”SecondGroup" /> </asp:Panel> </form> Теперь щелкните правой кнопкой мыши на поверхности визуального конструктора этой страницы и выберите в контекстном меню пункт View In Browser (Просмотреть в браузере), чтобы удостовериться, что проверка данных в элементах каждой панели про­ исходит во взаимоисключающей манере. И с х о д н ы й код. Веб-сайт V a l i d a t o r C t r l s доступен в подкаталоге C h a p t e r 33. Работа с темами До этих пор вы работали с многочисленными веб-элементами управления ASP. NETT. Как было показано, каждый из них предоставляет набор свойств (многие из которых унаследованы от Syst e m . W e b . U I . W e b c o n t r o l s . W e b C o n t r o l ) , позволяющих настраивать внешний вид и поведение этих элементов пользовательского интерфейса (цвет фона, размер шрифта, стиль рамки и т.п.). Конечно, на многостраничном веб-сайте принято определять общий внешний вид и поведение виджетов различных типов. Например, все T e x t B o x должны поддерживать определенный шрифт, все B u t t o n — иметь общий вид, а все C a l e n d a r — ярко-синюю рамку. Очевидно, что было бы очень трудоемкой (и чреватой ошибками) задачей задавать одинаковые установки свойств для каждого виджета на каждой странице веб-сайта. Даже если вы в состоянии вручную обновить свойства каждого виджета пользователь­ ского интерфейса на каждой странице, представьте, насколько мучительным может стать обновление цвета фона каждого TextBo x, когда это понадобится вновь. Ясно, что должен существовать другой путь применения настроек пользовательского интерфейса на уровне всего сайта. Один из возможных подходов, позволяющий упростить установку общего внешнего вида пользовательского интерфейса, заключается в определении таблиц стилей. Если у вас есть опыт веб-разработки, то вы знаете, что таблицы стилей определяют общий набор настроек пользовательского интерфейса, применяемых в браузере. Как и можно было ожидать, веб-элементы управления ASP.NETT могут принимать стиль за счет при­ сваивания значения свойству CssStyle. Однако ASP.NETT поставляется с дополняющей технологией для определения обще­ го пользовательского интерфейса, которая называется темами. В отличие от таблиц стилей, темы применяются на веб-сервере (а не в браузере) и могут использоваться как программно, так и декларативно. Учитывая, что тема применяется на веб-сервере, она имеет доступ ко всем серверным ресурсам веб-сайта. Более того, темы определяются написанием той же разметки, которую можно найти в любом файле *. as px (согласи­ тесь, что синтаксис таблиц стилей чересчур лаконичный). Вспомните из главы 32, что веб-приложения ASP. NETT могут определять любое коли­ чество “специальных” каталогов, один из которых — A p p Themes. Этот единственный каталог может быть дальше разбит на подкаталоги, каждый из которых представляет одну из возможных тем веб-сайта. Например, взгляните на рис. 33.22, на котором пока­ зан один каталог A p p Themes, содержащий три подкаталога, каждый из которых имеет набор файлов, образующих саму тему. Глава 33. Веб-элементы управления, мастер-страницы и темы ASP.NET 1 2 89 A pp^Them e Hoiiday_Theme Holiday.skin HolidayImages.xml Snow.tif Dramatic_Theme Premadonna.skin TheScream.tif Basic_Green SimpleCtrls.skin GridViewData.skin CompanyLogo.tif Рис. 33.22. Один каталог A p p T h e m e s может определять многочисленные темы Файлы * . s k i n Каждый подкаталог темы обязательно содержит файл *.skin. Эти файлы определя­ ют внешний вид и поведение различных веб-элементов управления. Для иллюстрации создайте новый веб-сайт по имени F u n W i t h T h e m e s . Добавьте новый файл *.s kin (ис­ пользуя пункт меню W e b s it e ^ A d d N e w Item) по имени B a s i c G r e e n . s k i n , как показано на рис. 33.23. Рис. 33.23. Вставка файла *.skin Среда Visual Studio 2010 предложит подтвердить добавление этого файла в А р р _ T h e m e s (что как раз и требуется). Если теперь заглянуть в Solution Explorer, в катало­ ге A p p T h e m e s будет виден подкаталог B a s i c G r e e n , который содержит новый файл BasicG r e e n . s k i n . В файле *.skin задается внешность и поведение различных виджетов с использова­ нием декларативного синтаксиса элементов управления ASP.NET. К сожалению, в IDEсреде не предусмотрена поддержка визуального конструктора для файлов *. skin . Один из способов сокращения объема ввода состоит в добавлении к программе временного файла *.aspx (например, temp.aspx), который может быть использован для построения пользовательского интерфейса виджетов с помощью визуального конструктора страниц Visual Studio 2010. 1 2 9 0 Часть VII. Построение веб-приложений с использованием ASP.NET Полученную в результате разметку можно затем скопировать в файл *.s k in . При этом, однако, вы обязаны удалить атрибут I D каждого веб-элемента управления. Это имеет смысл, поскольку мы не определяем вид и поведение конкретного элемента B u t t o n (например), а всех элементов B u t t o n . С учетом сказанного, вот как может выглядеть разметка для B a s i c G r e e n . s k i n , ко­ торая определяет внешний вид и поведение по умолчанию для типов B u t t o n , T e x t B o x и C a le n d a r: <asp:Button runat="server" BackColor="#80FF80"/> <asp:TextBox runat="server" BackColor="#80FF80"/> <asp:Calendar runat="server" BackColor="#80FF80"/> Обратите внимание, что каждый виджет по-прежнему имеет атрибут r u n a t = " s e r v e r " (что обязательно), и ни одному из них не назначен атрибут ID. Теперь определим вторую тему по имени C r a z y O r a n g e . Используя Solution Explorer, щелкните правой кнопкой мыши на папке A p p T h e m e s и добавьте новую тему по имени C r a z y O r a n g e . Это приведет к созданию нового подкаталога внутри папки A p p T h e m e s . Затем щелкните правой кнопкой мыши на новой папке C r a z y O r a n g e в Solution Explorer и выберите в контекстном меню пункт Add New Item (Добавить новый эле­ мент). В открывшемся диалоговом окне добавьте новый файл * . s k i n . Обновите файл C r a z y O r a n g e . s k i n , определив уникальный внешний вид и поведение для тех же веб­ элементов управления. Например: <asp:Button runat="server" BackColor="#FF8000"/> <asp:TextBox runat="server" BackColor="#FF8000"/> <asp:Calendar BackColor="White" BorderColor="Black" BorderStyle="Solid" CellSpacing="l" Font-Names="Verdana" Font-Size="9pt" ForeColor="Black" Height="250px" NextPrevFormat="ShortMonth" Width="330px" runat="server"> <SelectedDayStyle BackColor="#333399" ForeColor="White" /> <OtherMonthDayStyle ForeColor="#999999" /> <TodayDayStyle BackColor="#999999" ForeColor="White" /> <DayStyle BackColor="#CCCCCC" /> <NextPrevStyle Font-Bold="True" Font-Size="8pt" ForeColor="White" /> <DayHeaderStyle Font-Bold="True" Font-Size="8pt" ForeColor="#333333" Height="8pt" /> <TitleStyle BackColor="#333399" BorderStyle="Solid" Font-Bold="True" Font-Size="12pt" ForeColor="White" Height="12pt" /> </asp:Calendar> После этого окно Solution Explorer должно выглядеть, как показано на рис. 33.24. ’ Solution Explorer I] ^ ! 13 П Х Э Solution 'FunWithThemes (1 project) л .Р H:\_\FunWithThemes\ App_Data App_Themes л л BasicGreen л CrazyOrange ^ ^ BasicGreen.skin CrazyOrange-skin "~l Default.aspx web.config E l Model Browser R? Class View Solution Explor... Рис. 33.24. Веб-сайт с несколькими темами Глава 33. Веб-элементы управления, мастер-страницы и темы ASP.NET 1291 Теперь, когда сайт имеет множество тем, возникает следующий логичный вопрос: как применить их к страницам? Как и можно было ожидать, существует несколько пу­ тей сделать это. На заметку! Дизайн рассматриваемых примеров тем довольно прост (с целью экономии места на печатной странице). Вы можете развить их по своему вкусу. Применение тем ко всему сайту Если вы хотите обеспечить оформление каждой страницы сайта в одной и той же теме, проще всего обновить файл W e b . c o n f i g . Откройте текущий файл W e b . c o n f i g и определите элемент < p a g e s > внутри контекста корневого элемента < s y s t e m . w e b > . Добавление атрибута t h e m e к элементу < p a g e s > гарантирует применение одной и той же темы ко всем страницам сайта (разумеется, значением этого атрибута должно быть имя одного из подкаталогов внутри A p p T h e m e s ) . Ниже показано основное изменение: <configuration> <system.web> <pages theme="BasicGreen"> </pages> </system.web> </configuration> Если теперь добавить различные элементы B u t t o n , C a l e n d a r и T e x t B o x к файлу и запустить приложение, каждый виджет получит пользовательский ин­ терфейс, определенный темой B a s i c G r e e n . Если изменить значение атрибута темы на C r a z y O r a n g e и снова запустить приложение, пользовательский интерфейс будет соот­ ветствовать заданному темой C r a z y O r a n g e . D e fa u lt.a s p x Применение тем на уровне страницы Темы также можно применять к отдельным страницам. Это полезно в различных ситуациях. Например, возможно, в файле W e b . c o n f i g определена тема для всего сайта (как описано в предыдущем разделе); однако определенной странице должна быть на­ значена другая тема. Для этого понадобится просто обновить директиву < % @ Р а д е > . При использовании Visual Studio 2010 средство IntelliSense отобразит все доступные темы, определенные в папке А р р _ T h e m e s . <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inhents="_Default" Theme ="CrazyOrange" %> Поскольку этой странице назначена тема C r a z y O r a n g e , а в файле W e b . c o n f i g ука­ зана тема B a s i c G r e e n , то все страницы кроме этой будут визуализированы с темой B a s ic G re e n . Свойство S k in ID Иногда может потребоваться определить набор возможных внешних видов для от­ дельного виджета. Например, предположим, что необходимо определить два возможных пользовательских интерфейса для типа B u t t o n внутри темы C r a z y O r a n g e . В этом слу­ чае для различения каждого варианта внешнего вида служит свойство S k i n I D элемента управления внутри файла *.sk in : <asp:Button runat="server" BackColor="#FF8000"/> <asp:Button runat="server" SkinID = "BigFontButton" Font-Size="30pt" BackColor="#FF8000"/> 1 2 92 Часть VII. Построение веб-приложений с использованием ASP.NET Теперь, если есть страница, которая использует тему CrazyOrange, каждому элеменTyButtonno умолчанию будет назначена неименованная обложка Button. Если необ­ ходимо иметь несколько разных кнопок в одном файле *.aspx, используйте обложку BigFontButton, просто указывая ее в свойстве SkinID: <asp:Button ID="Button2" runat="server" SkinID="BigFontButton" Text="Button" / x b r /> Программное назначение тем И последнее, что мы рассмотрим — назначение темы в коде. Это может пригодить­ ся, когда необходимо предоставить конечным пользователям возможность выбора темы для текущего сеанса. Конечно, мы еще не рассматривали построение веб-приложений с поддержкой состояния, поэтому выбранная подобным образом тема будет утеряна между обратными отправками. В реальном рабочем сайте текущая тема пользователя сохраняется внутри переменной сеанса или же записывается в базу данных. Для иллюстрации программного назначения темы добавьте к пользовательскому интерфейсу в файле Default.aspx три элемента управления Button, как показано на рис. 33.25. Обработайте событие Click каждого из этих элементов Button. «veb-c.nnbg Object Browser Fun with Themes tBsp:BUttOB»btnNj?Tfone) I to T h e m e jo G r e e n T h e m e j b tn O ra n g e T h e m e | Here are the controb which will be themed February 2010 Sun M o n T u e M e d Thu > F ri Sat 31 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 2i 23 24 1C 26 27 ->o i ■> i A c * D e s ig n П S p lit *1 S o u rc e c 4 [< d n >! < aspButton*btnNoTheme> Рис. 33.25. Обновленный пользовательский интерфейс примера применения тем Теперь имейте в виду, что назначать тему программно можно только на опреде­ ленных фазах жизненного цикла страницы. Обычно это делается внутри обработчика события Page Prelnit. С учетом сказанного, модифицируйте файл кода следующим образом: partial class _Default : System.Web.UI.Page { protected void btnNoTheme_Click(object sender, System.EventArgs e) { // Пустая строка означает, что тема не применяется. Session["UserTheme"] = // Снова инициировать событие Prelnit. Server.Transfer(Request.FilePath); } protected void btnGreenTheme_Click (object sender, System.EventArgs e) . { Session["UserTheme"] = "BasicGreen"; Глава 33. Веб-элементы управления, мастер-страницы и темы ASP.NET 1293 // Снова инициировать событие Prelnit. Server.Transfer(Request.FilePath); } protected void btnOrangeTheme_Click(object sender, System.EventArgs e) { Session["UserTheme"] = "CrazyOrange"; // Снова инициировать событие Prelnit. Server.Transfer(Request.FilePath); } protected void Page_PreInit(object sender, System.EventArgs e) { try { Theme = Session ["UserTheme" ]. ToStnng () ; } catch { Theme = "" ; } } } Обратите внимание, что выбранная тема сохраняется в переменной сеанса (детали ищите в главе 34) по имени UserTheme, значение которой формально присваивается внутри обработчика событий Page Prelnit (). Когда пользователь щелкает на задан­ ной кнопке Button, мы вновь программно инициируем событие Prelnit, вызывая для этого метод Server.TransferO и вновь запрашивая текущую страницу. Запустив эту страницу, вы обнаружите, что можно переключать темы щелчками на разных кнопках Button. Исходный код. Веб-сайт FunWithThemes доступен в подкаталоге Chapter 33. Резюме В этой главе рассматривалось использование разнообразных веб-элементов управле­ ния ASP.NET. Начали мы с изучения роли базовых классов Control и WebControl, после чего перешли к рассмотрению динамического взаимодействия с внутренней коллекцией элементов управления панели. По пути мы познакомились с новой моделью навигации сайта (файлами * . sitemap и компонентом SiteMapDataSource), новым механизмом привязки данных (через компонент SqlDataSource и элемент управления GridView), а также различными элементами управления проверкой достоверности. Вторая часть главы была посвящена роли мастер-страниц и темам. Вспомните, что мастер-страницы могут использоваться для определения общей разметки для набора страниц сайта. Также вспомните, что файл *. master определяет любое количество мест заполнения содержимым, куда страницы содержимого вставляют свои элементы поль­ зовательского интерфейса. И, наконец, было показано, каким образом с помощью ме­ ханизма тем ASP.NET декларативно или программно применять общий внешний вид и поведение пользовательского интерфейса к виджетам на веб-сервере.