Пользовательские элементы управления
Второй способ
Есть еще один способ обеспечить доступ к компонентам, интегрированным в пользовательский элемент управления, это добавить в пользовательский элемент по дополнительному свойству, возвращающее ссылку на каждый компонент. При этом нужно использовать только get -аксессоры, поскольку адреса компонентов менять нельзя. В дальнейшем через это свойство-ссылку, доступную из страницы, можно обратиться к любым членам раскрытого таким образом компонента, входящего в состав пользовательского элемента.
Поясним сказанное на предыдущем примере.
-
Скопируйте через панель Solution Explorer, как это мы делали ранее, файл тестовой страницы MyControlTest.aspx и файл пользовательского элемента управления MyControl.ascx
-
Присвойте копиям новые имена MyControlExtTest.aspx и MyControlExt.ascx соответственно (файлы сопровождающего скрытого кода оболочка переименует автоматически)
-
Сделайте страницу MyControlExtTest.aspx стартовой, выполнив на ее узле в панели Solution Explorer команду Set As Start Page
-
Измените параметр Src директивы регистрации в файле MyControlExtTest.aspx
<%@ Register Src="MyControlExt.ascx" TagName="MyControl" TagPrefix="uc1" %>
-
Откройте файл скрытого кода MyControlExt.ascx.cs и измените в нем класс MyControl, чтобы он выглядел так
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 MyControlExt : System.Web.UI.UserControl { // Раскрываем весь компонент Label1 // Имя свойства InnerLabel1 выбрали произвольно // Используется только get-аксессор public Label InnerLabel1 { get { return Label1; } } }
-
Скорректируйте в файле MyControlExt.ascx атрибут директивы Control так Inherits="MyControlExt"
-
Откройте файл MyControlExtTest.aspx.cs скрытого кода тестовой страницы и отредактируйте его для доступа к прямым свойствам компонента Label1 с использованием созданного адреса InnerLabel1
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 MyControlExtTest : System.Web.UI.Page { protected void RadioButtonList1_SelectedIndexChanged(object sender, EventArgs e) { int index = RadioButtonList1.SelectedIndex; // Доступ к прямым свойствам компонента Label1 выполняем // через ссылку на этот компонент в родителе MyControl1 switch (index) { case 0: MyControl1.InnerLabel1.ForeColor = System.Drawing.Color.White; MyControl1.InnerLabel1.BackColor = System.Drawing.Color.Red; break; case 1: MyControl1.InnerLabel1.ForeColor = System.Drawing.Color.Aqua; MyControl1.InnerLabel1.BackColor = System.Drawing.Color.Green; break; case 2: MyControl1.InnerLabel1.ForeColor = System.Drawing.Color.Yellow; MyControl1.InnerLabel1.BackColor = System.Drawing.Color.Blue; break; } if(index != -1) MyControl1.InnerLabel1.Text = RadioButtonList1.Items[index].Value; } }
-
Выполните страницу и убедитесь, что получился тот же самый результат, что и в предыдущем примере при реализации первого способа
Какой способ выбрать - решать Вам.
Динамическое создание пользовательского элемента управления
На протяжении этой темы мы рассматривали вопрос создания пользовательского элемента управления в режиме проектирования и последующее управление им в программном режиме. Но может потребоваться на странице подгружать и настраивать пользовательский элемент управления динамически ("на лету"). Мы уже программно создавали из библиотечного элемента управления HtmlTable объект-таблицу на странице DynamicTable.aspx. Теперь посмотрим, как это делается для пользовательского элемента управления.
Требуется выполнить следующие шаги:
- Создавать при каждой загрузке страницы в обработчике ее события Page.Load экземпляр класса пользовательского элемента управления, заранее подготовленного в файлах *.ascx и *.ascx.cs. Создание и регистрация экземпляра пользовательского элемента в коде страницы осуществляется статическим методом Page.LoadControl().
- Резервировать с помощью элемента PlaceHolder место размещения для точного позиционирования на странице пользовательского элемента управления.
- Обязательно присваивать после динамического создания значение свойства ID пользовательского элемента управления, особенно, когда создается несколько экземпляров одного и того же элемента. Это может понадобиться для однозначной идентификации элемента в коде страницы при поиске ссылки на экземпляр, выполняемом с помощью статического метода Page.FindControl(), который как раз использует значение идентификатора ID.
Есть некоторая специфика динамического создания пользовательского элемента управления. Нельзя создать пользовательский элемент напрямую, как это делается с библиотечным элементом управления через конструктор класса. Пользовательский элемент управления состоит не только из поддерживающего класса в файле *.ascx.cs, но и дескрипторной части файла *.ascx. Поэтому на этапе проектирования он не представлен общим классом, экземпляр которого можно было-бы создать с помощью конструктора. Экземпляр пользовательского элемента управления создается самой ASP.NET объединением этих двух частей на этапе выполнения.
-
Скопируйте через панель Solution Explorer, как это мы делали ранее, файл тестовой страницы MyControlExtTest.aspx и файл пользовательского элемента управления MyControlExt.ascx
-
Присвойте копиям новые имена MyControlDynamicTest.aspx и MyControlDynamic.ascx соответственно (файлы сопровождающего скрытого кода оболочка переименует автоматически)
-
Сделайте страницу MyControlDynamicTest.aspx стартовой, выполнив на ее узле в панели Solution Explorer команду Set As Start Page
-
Закройте все предыдущие редактируемые документы командой меню Window/Close All Documents
-
Откройте на редактирование страницу MyControlDynamicTest.aspx в режиме Design, удалите наш пользовательский элемент управления Label1 и поместите на его место из вкладки Standard стандартный элемент управления PlaceHolder
-
Перейдите в файле MyControlDynamicTest.aspx в режим Source редактора страницы и удалите полностью старый код директивы регистрации
<%@ Register Src="MyControlExt.ascx" TagName="MyControl" TagPrefix="uc1" %>
На данном этапе страница в дескрипторном представлении будет такой
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="MyControlDynamicTest.aspx.cs" Inherits="MyControlTest" %> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> <asp:PlaceHolder ID="PlaceHolder1" runat="server" /> <br /> <br /> <asp:RadioButtonList ID="RadioButtonList1" runat="server" RepeatDirection="Horizontal"> <asp:ListItem Value="Red">Красный</asp:ListItem> <asp:ListItem Value="Green">Зеленый</asp:ListItem> <asp:ListItem Value="Blue">Синий</asp:ListItem> </asp:RadioButtonList> <br /> <input id="Submit1" type="submit" value="submit" /> </div> </form> </body> </html>
Все, теперь пользовательский элемент управления на странице не существует! Вместо него существует пустое место PlaceHolder1. Далее мы программно должны создать этот элемент, добавить ссылку на него к странице, а потом и управлять свойствами его компонентов.
-
Откройте на редактирование файл скрытого кода MyControlDynamicTest.aspx.cs, выполнив команду контекстного меню View Code редактора
-
Измените код обработчика 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 MyControlTest : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { // Создаем экземпляр класса поддержки // пользовательского элемента управления MyControl MyControl1 = (MyControl)Page.LoadControl("MyControlDynamic.ascx"); // Добавляем объект в зарезервированное место страницы PlaceHolder1.Controls.Add(MyControl1); int index = RadioButtonList1.SelectedIndex; // Доступ к прямым свойствам компонента Label1 выполняем // через ссылку на этот компонент в родителе MyControl1 switch (index) { case 0: MyControl1.InnerLabel1.ForeColor = System.Drawing.Color.White; MyControl1.InnerLabel1.BackColor = System.Drawing.Color.Red; break; case 1: MyControl1.InnerLabel1.ForeColor = System.Drawing.Color.Aqua; MyControl1.InnerLabel1.BackColor = System.Drawing.Color.Green; break; case 2: MyControl1.InnerLabel1.ForeColor = System.Drawing.Color.Yellow; MyControl1.InnerLabel1.BackColor = System.Drawing.Color.Blue; break; } if(index != -1) MyControl1.InnerLabel1.Text = RadioButtonList1.Items[index].Value; } }
Обратите внимание, что при наборе кода создания пользовательского элемента в редакторе кода механизм IntelliSense нам не помогает, потому что страница не знает, что где-то в файле MyControlDynamic.ascx существует класс MyControl.
Преобразование страницы в пользовательский элемент управления
Чаще пользовательский элемент управления проще сделать из обычной страницы .aspx, чем мы и воспользуемся ниже. Это делается так:
- Сначала нужно разработать обычную страницу, отладить ее и проверить в действии.
- Переименовать расширение файла из aspx в ascx
- Директиву @Page вместе с ее атрибутами следует удалить и заменить директивой @Control с требуемыми атрибутами.
- Удалить из кода все дескрипторы <html>, <body>, <form>, <head>.
- В коде файла поддержки заменить базовый класс Page на UserControl.
- Если мы используем модель совмещенного кода, то нужно в директиву Control обязательно добавить атрибут ClassName="имя_файла_или_любое_имя". Он извещает ASP.NET, что код, который нужно компилировать, находится в том же файле в дескрипторах <script>. Без этой информации файл компилироваться не будет.