Лень – двигатель
прогресса. Практически все открытия и усовершенствования сделаны от
того, что людям хочется за меньшее время и с меньшими усилиями получить
результат. Одним из таких усовершенствований является и компонентное
программирование – технология, действительно резко облегчившая создание
программ с помощью уже готовых модулей. Ведь собрать уже написанные
кем-то кирпичики и скрепить их вместе цементом своего кода для получения
готовой программы-дома намного проще, чем писать эту программу полностью
с нуля. Одним из примеров применения компонентного программирования в
разработке веб приложений является технология пользовательских элементов
управления, введенная в ASP.NET. Используя пользовательские элементы
управления программист может создать множество модулей и потом
«собирать» страницы своего сайта из этих модулей. Например наш сайт,
сделанный на основе IBuySpy Portal Sample – великолепном примере
создания сайта с помощью технологии ASP.NET и с использованием
пользовательских элементов управления, состоит буквально из нескольких
страниц (можно было бы обойтись и одной страницей, но в целях удобства я
этого не делал) и множества пользовательских элементов управления, по
мере необходимости добавляемых на выводимые страницы. Создав один раз
пользовательский элемент управления можно использовать его потом на
любой странице сайта не заботясь ни о его внешнем виде, ни о
программировании (например, если я захочу добавить модуль «Полезные
ссылки» с главной страницы нашего сайта на страницу со списком статей –
мне нужно будет только добавить код вставки этого пользовательского
элемента управления на страницу).
Скептики скажут – «использование пользовательских элементов
управления похоже на использование старых добрых include файлов, верой и
правдой служивших нам много лет». Но не торопитесь, хоть
пользовательские элементы возможно и похожи на include файлы, но только
похожи.
Я думаю теории и восхвалений достаточно – пора перейти к делу и
создать пару-тройку примеров пользовательских элементов управления.
Итак есть следующая задача: есть сайт, на котором на каждой странице
необходимо разместить его название. Задача конечно же банальная и очень
просто решаемая с помощью include фалов, но в этой статье все таки
рассматриваются пользовательские элементы управления и поэтому мы
создадим пользовательский элемент управления для ее решения, а заодно и
рассмотрим базовые вопросы создания и применения пользовательских
элементов управления.
Пользовательский элемент управления представляет собой файл с
расширением .ascx. Базовым классом для класса пользовательского элемента
управления должен быть класс System.Web.UI.UserControl. Вооружившись
этими данными создадим наш первый пользовательский элемент управления.
Вот код ascx файла:
<%@ Control Language="c#" Codebehind="header.ascx.cs" Inherits="UserControls.Step1.header"%>
<TABLE cellSpacing=2 cellPadding=2 align=center border=0>
<TR>
<TD>Пользовательские элементы управления</TD>
</TR>
</TABLE>
Код класса в codebehind файле на данном этапе не представляет
никакого интереса так как мы не добавляли никакой функциональности к
пользовательскому элементу управления. Единственная строка, которая
может быть нам интересна, это строка объявления класса нашего
пользовательского элемента управления:
public abstract class header : System.Web.UI.UserControl
Как можно видеть из этой строки, класс нашего элемента управления
порожден от класса System.Web.UI.UserControl – базового класса для всех
пользовательских элементов управления.
Первый пользовательский элемент управления успешно написан – теперь
надо бы его как-то использовать (а иначе зачем нужно было его вообще
писать? :)). Вставка пользовательского элемента управления в веб форму
происходит в два этапа. Вначале необходимо зарегистрировать наш элемент
управления на странице. Это делается с помощью тега <#@ Register %>:
<%@ Register TagPrefix="uc1" TagName="header" Src="header.ascx" %>
Атрибуты данного тега имеют следующее назначение:
TagName |
Определяет неймспейс (префикс)
пользовательского элемента управления |
TagPrefix |
Определяет имя пользовательского элемента
управления |
Src |
Виртуальный путь к файлу пользовательского
элемента управления. |
После регистрации пользовательского элемента управления на странице
его можно использовать следующим образом:
<TegName:TagPrefix id=”id” runat="server" />
и для нашего случая для вставки созданного и зарегистрированного
пользовательского элемента управления нужна следующая конструкция:
<uc1:header id=Header1 runat="server" />
Существует еще одна возможность добавления пользовательского элемента
управления в веб форму. При этом в код веб формы никакого
дополнительного кода не вносится, а пользовательский элемент управления
загружается и добавляется на страницу в коде класса веб формы. Именно
этот способ применяется на нашем сайте для отображения модулей.
Для загрузки пользовательского элемента управления в этом случае
используется метод Page.LoadControl, возвращающий экземпляр класса
System.Web.UI.Control, содержащий загружаемый элемент управления. И, как
и всякий другой элемент управления, загруженный пользовательский элемент
управления может быть добавлен в коллекцию элементов управления веб
формы:
private void Page_Load(object sender, System.EventArgs e)
{
if(!IsPostBack)
{
Page.Controls.AddAt(0, Page.LoadControl("header.ascx"));
}
}
Как видите ничего сложного. Хотя и задача перед нами стояла далеко не
сверхсложная :).
Продолжим изучение нашей темы и рассмотрим теперь пример управления
пользовательским элементом управления извне. Например добавим
возможность вывода кроме названия сайта также и название текущего
раздела сайта и кроме этого добавим возможность форматирования выводимых
данных (например цвет фона).
Управление пользовательским элементом управления происходит с помощью
его свойств. Для приведенного выше задания нам необходимо добавить два
публичных свойства к нашему элементу управления – Title (для имени
страницы) и Bgcolor (для фона текста) и вывести их значения в
соответствующих местах нашего элемента управления. Нет ничего проще :).
Итак в классе пользовательского элемента управления определяем два
публичных свойства:
public string Title
{
get
{
if(ViewState["Title"] == null)
return "";
else
return (string) ViewState["Title"];
}
set
{
ViewState["Title"] = value;
}
}
public Color Bgcolor
{
get
{
if(ViewState["Bgcolor"] == null)
return Color.White;
else
return (Color) ViewState["Bgcolor"];
}
set
{
ViewState["Bgcolor"] = value;
}
}
А в коде пользовательского элемента управления выведем их значения:
<%@ Control Language="c#" Codebehind="header.ascx.cs" Inherits="UserControls.Step2.header" AutoEventWireup="false" %>
<TABLE cellSpacing=2 cellPadding=2 align=center border=0 bgcolor="<%=System.Drawing.ColorTranslator.ToHtml(Bgcolor)%>">
<TR>
<TD align=middle>Пользовательские элементы управления</TD>
</TR>
<TR>
<TD align=middle><%=Title%></TD>
</TR>
</TABLE>
Пользовательский элемент управления написан и расширен, но как теперь
в него передать параметры? Данный вопрос также имеет простое решение,
даже два. Во-первых, можно указать значения параметров в качестве
значений атрибутов при объявлении пользовательского элемента управления
на странице, например так:
<uc1:header id=Header1 Title="Главная страница" runat="server" Bgcolor="Red" />
Как видно на этом примере атрибутам Title и Bgcolor присваиваются
значения соответственно «Главная страница» и Color.Red.
Во-вторых, можно установить свойства пользовательского элемента
управления в коде класса веб формы. Для этого необходимо добавить
объявление защищенной/публичной переменной – пользовательского элемента
управления в код класса веб формы, после чего можно будет манипулировать
свойствами пользовательского элемента управления:
public class news : System.Web.UI.Page
{
protected UserControls.Step2.header Header1;
private void Page_Load(object sender, System.EventArgs e)
{
if(!IsPostBack)
{
Header1.Title = "Новости";
Header1.Bgcolor = Color.LightSalmon;
}
}
...
}
Приведенные выше примеры не несли в себе особой функциональной
нагрузки. Настала пора восполнить этот пробел и создать пользовательский
элемент управления не только для отображения передаваемых ему
параметров. Следующим (и последним обучающим в данной статье) шагом
будет добавление формы аутентификации к нашему элементу управления.
Причем если пользователь уже прошел аутентификацию вместо формы
аутентификации будет выведено приветствие.
Как я уже упоминал, пользовательский элемент управления представляет
собой часть веб формы. И, как и всякая веб форма, пользовательский
элемент управления может содержать любые серверные контролы (в том числе
и другие пользовательские элементы управления). Исходя из этого добавим
к нашему пользовательскому элементу управления некоторую
функциональность, которая позволит пользователю проходить аутентификацию
на сайте.
Код веб формы:
<%@ Control Language="c#" Codebehind="header.ascx.cs" Inherits="UserControls.Step3.header" AutoEventWireup="false" %>
<TABLE cellSpacing=2 cellPadding=2 align=center bgColor="<%=System.Drawing.ColorTranslator.ToHtml(Bgcolor)%>" border=0>
<TR>
<TD align="middle">Пользовательские элементы управления</TD>
</TR>
<TR>
<TD align="middle"><%=Title%></TD>
</TR>
<tr id="trLogin" runat="server">
<td align="middle">
<TABLE cellSpacing="2" cellPadding="2" align="center" border="0">
<TR>
<TD>Имя</TD>
<TD>
<asp:TextBox id="txtLogin" runat="server" Columns="10"></asp:TextBox></TD>
<TD>Пароль</TD>
<TD>
<asp:TextBox id="txtPassword" runat="server" Columns="10"></asp:TextBox></TD>
</TR>
<TR>
<TD align="middle" colSpan="4">
<asp:Button id="btnLogin" runat="server" Text="Вход"></asp:Button></TD>
</TR>
</TABLE>
</td>
</tr>
<tr id="trLogged" runat="server" Visible="False">
<td align="middle">
<asp:Label id="lblLoginName" runat="server"></asp:Label>
</td>
</tr>
</TABLE>
Как видно из кода в таблицу, выводимую пользовательским элементом
управления, были добавлены 2 строки. Обе строки имеют атрибуты id и
runat=server, что позволяет манипулировать ими на стороне сервера. В
случае, если пользователь еще не прошел аутентификацию, будет показана
первая строка таблицы (id=”trLogin”), в которой размещены элементы
управления для аутентификации пользователя. Вторая строка будет показана
только аутентифицированному пользователю и будет содержать приветствие.
Код класса пользовательского элемента управления:
namespace UserControls.Step3
{
using System;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
public abstract class header : System.Web.UI.UserControl
{
protected System.Web.UI.HtmlControls.HtmlTableRow trLogin;
protected System.Web.UI.WebControls.TextBox txtLogin;
protected System.Web.UI.WebControls.TextBox txtPassword;
protected System.Web.UI.HtmlControls.HtmlTableRow trLogged;
protected System.Web.UI.WebControls.Label lblLoginName;
protected System.Web.UI.WebControls.Button btnLogin;
public string Title
{
get
{
if(ViewState["Title"] == null)
return "";
else
return (string) ViewState["Title"];
}
set
{
ViewState["Title"] = value;
}
}
public Color Bgcolor
{
get
{
if(ViewState["Bgcolor"] == null)
return Color.White;
else
return (Color) ViewState["Bgcolor"];
}
set
{
ViewState["Bgcolor"] = value;
}
}
private void Page_Load(object sender, System.EventArgs e)
{
if(!IsPostBack)
if(Context.User.Identity.IsAuthenticated)
{
trLogged.Visible = true;
trLogin.Visible = false;
lblLoginName.Text = "Добро пожаловать, " + Context.User.Identity.Name + "!";
}
}
override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
}
private void InitializeComponent()
{
this.btnLogin.Click += new System.EventHandler(this.btnLogin_Click);
this.Load += new System.EventHandler(this.Page_Load);
}
private void btnLogin_Click(object sender, System.EventArgs e)
{
if(txtLogin.Text.ToLower() != "guest")
{
System.Web.Security.FormsAuthentication.SetAuthCookie(txtLogin.Text, false);
Response.Redirect(Request.UrlReferrer.ToString());
}
}
}
}
Как видите в коде класса пользовательского элемента управления
произошли некоторые изменения. Во-первых, в обработчик Page_Load был
добавлен код, проверяющий аутентифицирован ли пользователь и выводящий
соответствующую строку таблицы пользовательского элемента управления.
Также был добавлен код для аутентификации пользователя (метод
btnLogin_Click – обработчик события Click кнопки). В этом методе
происходит примитивная проверка введенного имени пользователя
(пользователь считается прошедшим аутентификацию если введенное им имя
не равно guest) после чего пользователь аутентифицируется на сайте с
помощью метода SetAuthCookie и страница перегружается (так как
необходимо обновить выводимую в пользовательском элементе управления
информацию). Не забудьте изменить файл web.config (добавить строку
<authentication mode="Forms" />) иначе данный код работать не будет.
И еще одно важное замечание к последнему примеру. Хоть
пользовательские элементы управления теоретически можно размещать в
любом месте веб страницы, пользовательские элементы управления,
содержащие элементы управления, генерирующие события, обязательно должны
располагаться внутри тега <form runat="server">.
Хоть рассмотренный в этой статье пример и мал, но используя его вы
уже можете добавив всего несколько строк в любую веб форму вашего сайта
выводить на веб форме название сайта, страницы и формы для
аутентификации пользователей и применять к выводимой информации
минимальное форматирование. Пользовательские элементы управления
позволяют создавать небольшие куски веб форм с необходимой
функциональностью и использовать их потом на нужных страницах вашего
сайта. Использование пользовательских элементов управления позволяет
сократить время создания сайта и дает немало других преимуществ. |