Лень – двигатель прогресса. Практически все открытия и усовершенствования сделаны от того, что людям хочется за меньшее время и с меньшими усилиями получить результат. Одним из таких усовершенствований является и компонентное программирование – технология, действительно резко облегчившая создание программ с помощью уже готовых модулей. Ведь собрать уже написанные кем-то кирпичики и скрепить их вместе цементом своего кода для получения готовой программы-дома намного проще, чем писать эту программу полностью с нуля.
Одним из примеров применения компонентного программирования в разработке веб приложений является технология пользовательских элементов управления, введенная в 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">.
Хоть рассмотренный в этой статье пример и мал, но используя его вы уже можете добавив всего несколько строк в любую веб форму вашего сайта выводить на веб форме название сайта, страницы и формы для аутентификации пользователей и применять к выводимой информации минимальное форматирование. Пользовательские элементы управления позволяют создавать небольшие куски веб форм с необходимой функциональностью и использовать их потом на нужных страницах вашего сайта. Использование пользовательских элементов управления позволяет сократить время создания сайта и дает немало других преимуществ. |