Пользовательские элементы управления
Доступ из кода Web-страницы к составным компонентам пользовательского элемента управления
Web-страница, которая содержит интегрированный в нее пользовательский элемент управления, не может без дополнительных приемов получать доступ к компонентам этого элемента: к их методам, событиям, свойствам. Такое положение является обоснованным, чтобы случайно в Web-странице не внести нежелательные изменения в ее дочерний элемент.
Но учитывая, что сам пользовательский элемент имеет доступ к своим компонентам, а страница имеет доступ к пользовательскому элементу, это правило можно обойти. Для этого существует два способа:
- Ввести в класс пользовательского элемента дополнительные свойства и функции доступа к нужным членам индивидуально для каждого компонента
- Ввести в класс пользовательского элемента управления для каждого компонента по одному дополнительному свойству, возвращающему ссылку на соответствующий компонент
Первый способ
В пользовательский элемент вводят промежуточные свойства или методы доступа, через которые из Web-страницы обращаются к его компонентам. Это напоминает прием, который применяется в C++ для поддержания инкапсуляции (закрытости) данных: переменные-члены класса с модификатором доступа private упаковывают в функции доступа public, которые сами видят эти переменные, а их, в свою очередь, видят клиенты этого класса.
Пусть, например, пользовательский элемент управления MyControl1 как объект порождается классом MyControl и в качестве одного из компонентов содержит в себе объект Label1 библиотечного класса System.Web.UI.WebControls.Label. Класс Label наследует от базового класса System.Web.UI.WebControls.WebControl свойство BackColor, которое, в свою очередь, имеет тип System.Drawing.Color. Напрямую из Web-страницы нельзя установить новое значение свойства BackColor компонента Label1 пользовательского элемента. Но можно раскрыть это свойство для Web-страницы, введя промежуточное свойство BackColor (или с другим именем) в классе самого пользовательского элемента. Сказанное схематично изображено на рисунке
Выполним это на практике.
-
Создайте заготовку пользовательского элемента Web User Control с именем MyControl.ascx с раздельным кодом (флажок Place code in separate file мастера включен) -
Перейдите в режим Design редактора заготовки и поместите на нее из вкладки Standard элемент Label с именем Label1
-
В панели Solution Explorer откройте файл поддержки MyControl.ascx.cs, удалите из класса MyControl заготовку обработчика Page_Load() за ненадобностью и дополните класс свойствами доступа, чтобы он стал таким
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class MyControl : System.Web.UI.UserControl
{
public string Text
{
get { return Label1.Text; }
set { Label1.Text = value; }
}
public System.Drawing.Color BackColor
{
get { return Label1.BackColor; }
set { Label1.BackColor = value; }
}
public System.Drawing.Color ForeColor
{
get { return Label1.ForeColor; }
set { Label1.ForeColor = value; }
}
}Здесь мы использовали имена посреднических свойств родителя MyControl1 точно такие, как у прямых свойств компонента Label1. Но это не обязательно. Можно использовать любые имена. Просто, когда Иванов, Петров, Сидоров означают одно и то же лицо, но в разных инстанция числятся по разному, это " хужее ".
-
Создайте пользовательскую тестовую страницу с раздельным кодом под именем MyControlTest.aspx и переведите ее в режим редактирования Design
-
Из панели Solution Explorer из дерева файлов приложения перенесите на тестовую страницу узел MyControl.ascx. Убедитесь, что экземпляр пользовательского элемента управления зарегистрировался на тестовой странице под именем MyControl1
-
Попробуйте выделить элемент управления и убедитесь, что он не выделяется и добавленные нами свойства не видны в панели Properties. Это значит, что декларативно (в режиме проектирования) из страницы настраивать его нелься, но можно программно управлять (в режиме выполнения) через введенные нами общедоступные свойства, в чем мы и хотим убедиться. -
Поместите на страницу под пользовательским элементом управления компонент RadioButtonList из вкладки Standard и убедитесь, что он имеет ID="RadioButtonList1"
-
Через коллекцию Items элемента RadioButtonList1 задайте три радиокнопки с такими свойствами
-
Установите свойство RepeatDirection элемента RadioButtonList1 в значение Horozontal
-
Выделите компонент RadioButtonList1 и через панель Properties создайте обработчик для его события SelectedIndexChanged
-
Под списком радиокнопок поместите компонент Input (Submit) из вкладки HTML
Дескрипторное представление страницы будет иметь вид
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="MyControlTest.aspx.cs"
Inherits="MyControlTest" %>
<%@ Register Src="MyControl.ascx" TagName="MyControl" TagPrefix="uc1" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<uc1:MyControl ID="MyControl1" runat="server" />
<br />
<br />
<asp:RadioButtonList ID="RadioButtonList1" runat="server"
RepeatDirection="Horizontal"
OnSelectedIndexChanged="RadioButtonList1_SelectedIndexChanged">
<asp:ListItem Value="Red">Красный</asp:ListItem>
<asp:ListItem Value="Green">Зеленый</asp:ListItem>
<asp:ListItem Value="Blue">Синий</asp:ListItem>
</asp:RadioButtonList></div>
<br />
<input id="Submit1" type="submit" value="submit" />
</form>
</body>
</html>Мы хотим, чтобы на клиенте при щелчке на кнопке Submit выполнялась обратная отсылка на сервер, где бы код страницы через введенные нами в класс пользовательского элемента управления дополнительные свойства менял настройку элемента Label1. Этот код смены настройки нужно поместить в созданный нами обработчик радиокнопок, чтобы он срабатывал каждый раз, когда получит обратную отсылку с требованием пользователя выполнить новые настройки. В результате элемент Label1 сгенерирует нужный HTML-код и отошлет его клиенту.
-
Заполните обработчик RadioButtonList1_SelectedIndexChanged() страницы в файле MyControlTest.aspx.cs следующим кодомusing System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; public partial class MyControlTest : System.Web.UI.Page { protected void RadioButtonList1_SelectedIndexChanged(object sender, EventArgs e) { int index = RadioButtonList1.SelectedIndex; switch (index) { case 0: MyControl1.ForeColor = System.Drawing.Color.White; MyControl1.BackColor = System.Drawing.Color.Red; break; case 1: MyControl1.ForeColor = System.Drawing.Color.Aqua; MyControl1.BackColor = System.Drawing.Color.Green; break; case 2: MyControl1.ForeColor = System.Drawing.Color.Yellow; MyControl1.BackColor = System.Drawing.Color.Blue; break; } if(index != -1) MyControl1.Text = RadioButtonList1.Items[index].Value; } } -
Откомпилируйте страницу и проверьте ее работоспособность. При щелчке на кнопке код страницы меняет свойства компонента Label1, хотя он входит в состав пользовательского элемента управления MyControl1. Взаимодействие страницы с Label1 происходит через добавленные нами в пользовательский элемент управления дополнительные глобальные свойства.
