Опубликован: 07.05.2010 | Доступ: свободный | Студентов: 1678 / 62 | Оценка: 4.56 / 4.06 | Длительность: 34:11:00
Лекция 6:

Пользовательские элементы управления

Второй способ

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

Требуется выполнить следующие шаги:

  1. Создавать при каждой загрузке страницы в обработчике ее события Page.Load экземпляр класса пользовательского элемента управления, заранее подготовленного в файлах *.ascx и *.ascx.cs. Создание и регистрация экземпляра пользовательского элемента в коде страницы осуществляется статическим методом Page.LoadControl().
  2. Резервировать с помощью элемента PlaceHolder место размещения для точного позиционирования на странице пользовательского элемента управления.
  3. Обязательно присваивать после динамического создания значение свойства 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, чем мы и воспользуемся ниже. Это делается так:

  1. Сначала нужно разработать обычную страницу, отладить ее и проверить в действии.
  2. Переименовать расширение файла из aspx в ascx
  3. Директиву @Page вместе с ее атрибутами следует удалить и заменить директивой @Control с требуемыми атрибутами.
  4. Удалить из кода все дескрипторы <html>, <body>, <form>, <head>.
  5. В коде файла поддержки заменить базовый класс Page на UserControl.
  6. Если мы используем модель совмещенного кода, то нужно в директиву Control обязательно добавить атрибут ClassName="имя_файла_или_любое_имя". Он извещает ASP.NET, что код, который нужно компилировать, находится в том же файле в дескрипторах <script>. Без этой информации файл компилироваться не будет.