Пользовательские элементы управления
Доступ из кода 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 происходит через добавленные нами в пользовательский элемент управления дополнительные глобальные свойства.