Опубликован: 13.07.2010 | Уровень: специалист | Доступ: платный
Самостоятельная работа 32:

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

Ниже мы убедимся, что программно загруженные в портальные каркасы пользовательские элементы управления обрабатывают свои события точно также, как будто бы каждый из них находится на отдельной исполнимой странице.

  • Откройте на редактирование файл DynamicUserControls.aspx.cs и добавьте в класс DynamicUserControls следующий код
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 DynamicUserControls : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        // Загружаем портальные каркасы
        MyLoadControls(Panel1);
        MyLoadControls(Panel2);
        MyLoadControls(Panel3);
    }
  
    // Вспомогательная функция
    private void MyLoadControls(Control containerPanel)
    {
        // Объявляем вспомогательные ссылки на интерфейсные
        // элементы текущего контейнера
        DropDownList list = null;
        PlaceHolder ph = null;
        Label lbl = null;
  
        // Перебираем все дочерние элементы текущего 
        // контейнера и ищем ссылки на объекты дочерних
        // интерфейсных элементов по их типам
        foreach (Control ctrl in containerPanel.Controls)
        {
            if (ctrl is DropDownList)
                list = (DropDownList)ctrl;
            else if (ctrl is PlaceHolder)
                ph = (PlaceHolder)ctrl;
            else if (ctrl is Label)
                lbl = (Label)ctrl;
        }
  
        // Берем информацию из выделенного
        // элемента списка текущего контейнера
        string lstValue = list.SelectedItem.Value;
        string lstText = list.SelectedItem.Text;
        lbl.Text = "";
  
        // Заполняем текущий контейнер.
        // Проверяем наличие нужного расширения
        if (lstValue.EndsWith(".ascx"))
        {
            ph.Controls.Add(Page.LoadControl(lstValue));
            lbl.Text = "Загрузили: " + lstValue + " - " + lstText;
        }
    }
}
Листинг 32.28. Код файла DynamicUserControls.aspx.cs

Пользовательский элемент управления иногда проще сделать из обычной страницы .aspx, выполнив следующие шаги:

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

Используя перечисленные шаги, создадим пользовательские элементы управления, которые реализуют пользовательский интерфейс и функциональность, использованную нами при выполнении предыдущих упражнений в тестовых страницах. Из этих тестовых страниц мы их и переделаем. Получится так, что пользовательский элемент управления будет включен в тестовую страницу, а сама тестовая страница будет превращена в пользовательский элемент и будет динамически включаться по выбору из списка на исполнимую страницу DynamicUserControls.aspx в зарезервированные PlaceHolder -места.

  • В панели Solution Explore выделите при нажатой клавише Ctrl следующие файлы
    • HeaderTest.aspx
    • TimeDisplayTest.aspx
    • LinkTableTest.aspx
    • MyControlTest.aspx
  • Выполните команду Copy затем Paste (на верхнем узле проекта) контекстного меню
  • Присвойте копиям те же самые имена, только с расширением .ascx
    • HeaderTest.ascx
    • TimeDisplayTest.ascx
    • LinkTableTest.ascx
    • MyControlTest.ascx
  • Откройте новые файлы в дескрипторном режиме и замените директиву @Page на @Control, все остальные атрибуты бывшей директивы @Page оставьте прежними. Теперь это будут не страницы, а пользовательские элементы управления. Директиву @Register с ее атрибутами изменять не нужно
  • Удалить из кода все дескрипторы <html>, <body>, <form>, <head> и закрывающие их дескрипторы

В результате новые пользовательские элементы должны иметь следующий код интерфейсной части

HeaderTest.ascx
<%@ Control AutoEventWireup="true" CodeFile="HeaderTest.ascx.cs" 
    Inherits="HeaderTest" Language="C#" %>
        
<%@ Register TagPrefix="myElem" TagName="Header" Src="Header.ascx" %>
    
<myElem:Header ID="Header1" runat="server" />
TimeDisplayTest.ascx
<%@ Control Language="C#" %>
    
<%@ Register Src="TimeDisplay.ascx" TagName="TimeDisplay" TagPrefix="uc1" %>
    
<uc1:TimeDisplay ID="TimeDisplay1" runat="server" Format="" />
<br />
<br />
<hr />
<br />
<uc1:TimeDisplay ID="TimeDisplay2" runat="server" 
     Format="Сегодня dddd, dd MMMM yyyy<br />Текущее время HH:mm:ss" />
LinkTableTest.ascx
<%@ Control AutoEventWireup="true" CodeFile="LinkTableTest.ascx.cs" 
    Inherits="LinkTableTest" Language="C#" %>
    
<%@ Register Src="LinkTable.ascx" TagName="LinkTable" TagPrefix="uc1" %>
    
<uc1:LinkTable ID="LinkTable1" runat="server" 
               OnLinkClicked="LinkTable1_LinkClicked" />
<br />
<asp:Label ID="lblInfo" runat="server"></asp:Label>
MyControlTest.ascx
<%@ Control AutoEventWireup="true" CodeFile="MyControlTest.ascx.cs" 
    Inherits="MyControlTest" Language="C#" %>
        
<%@ Register Src="MyControl.ascx" TagName="MyControl" TagPrefix="uc1" %>
    
<uc1:MyControl ID="MyControl1" runat="server" />
<br />
<br />
<asp:RadioButtonList ID="RadioButtonList1" runat="server" 
    OnSelectedIndexChanged="RadioButtonList1_SelectedIndexChanged"
    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" />
  • Для новых файлов *.ascx откройте файлы скрытого кода *.ascx.cs и замените в объявлении класса имя базового класса с " System.Web.UI.Page " на " System.Web.UI. UserControl "

Остальной код классов останется прежним. Мы закончили выполнение упражнения. Код исполнимой страницы DynamicUserControls.aspx при очередной загрузке будет программно создавать свои пользовательские элементы управления для каждого контейнера Panel и размещать их в элементах PlaceHolder.

  • Выполните страницу DynamicUserControls.aspx и испытайте ее работу

Результат будет примерно таким

Иногда при отладке приложения оболочка начинает сбоить, выдавая непонятные ошибки. Может помочь перезапуск Visual Studio 2005 или удаление файла web.config, все равно оболочка создаст его автоматически при очередной компиляции. Пока нам этот файл не жалко, потому что его настройками мы все-равно еще не занимались.


Иван Циферблат
Иван Циферблат
Россия, Таганрог, 36, 2000