Динамическая загрузка пользовательских элементов управления

115

До сих пор было показано, как добавлять пользовательские элементы управления на страницу путем регистрации типа пользовательского элемента управления и добавления соответствующего дескриптора. Пользовательские элементы управления можно создавать также динамически - другими словами, конструировать их "на лету" с помощью небольшого объема кода веб-страницы.

Эта технология аналогична приему, применяемому для динамического добавления обычных веб-элементов управления. Как и при работе с обычными элементами управления, потребуется выполнить следующие действия:

Однако существует один дополнительный нюанс. Объект пользовательского элемента управления нельзя создать напрямую, как это имело место при работе с обычным элементом управления. Дело в том, что пользовательские элементы управления создаются не только кодом - они нуждаются также в дескрипторах, которые определены в файле .ascx. Для взаимодействия с пользовательским элементом управления ASP.NET нужно обработать этот файл и инициализировать соответствующие объекты дочерних элементов управления.

Для этого должен быть вызван метод Page.LoadControl(). При вызове метода LoadControl() передается имя файла разметки .ascx пользовательского элемента управления. LoadControl() возвращает объект UserControl, который затем можно добавить в страницу.

Ниже приведен пример динамической загрузки пользовательского элемента управления TimeDisplay (созданного в предыдущей статье) и его добавления к странице с помощью элемента управления PlaceHolder:

protected void Page_Load(object sender, EventArgs e)
{
        var control = Page.LoadControl(@"~\TimeDisplay.ascx");
        PlaceHolder1.Controls.Add(control);
}

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

Портальные платформы

Хотя создание полноценной портальной платформы требует написание достаточно большого объема шаблонного кода, наиболее важные принципы можно продемонстрировать на простом примере. Взгляните на страницу, показанную на рисунке ниже. Она включает в себя панель, содержащую три элемента управления - DropDownList (свойство которого AutoPostBack установлено в true), Label и PlaceHolder:

Динамически загруженный пользовательский элемент управления

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

Код, загружающий выбранный элемент управления, выглядит следующим образом:

<html>
<head runat="server">
    <title>Основы ASP.NET</title>
    <style>
        .container {
            border:1px ridge;
            padding:10px;  
            font-size:x-small;
            margin:10px;
            background:#aaa;
            width:300px;
        }
    </style>
</head>
<body>    
    <form id="form1" runat="server">
        <div id="div1" runat="server" class="container">
            <asp:DropDownList ID="lstControls1" runat="server" Width="215px" AutoPostBack="True">
                <asp:ListItem Value="(None)">(None)</asp:ListItem>
                <asp:ListItem Value="Banner.ascx">Banner</asp:ListItem>
                <asp:ListItem Value="LinkTable.ascx">LinkTable</asp:ListItem>
            </asp:DropDownList>
            <br />
            <asp:PlaceHolder ID="PlaceHolder1" runat="server" />
            <br />
            <br />
            <asp:Label ID="PanelLabel1" runat="server" Font-Italic="True" EnableViewState="False" />
        </div>
    </form>
</body>
</html>
protected void Page_Load(object sender, System.EventArgs e)
    {
        // Помните, что элемент управления должен загружаться 
        // в обработчике события Page.Load.
        // Событие DropDownList.SelectedIndexChanged запускается слишком поздно
        string ctrlName = lstControls1.SelectedItem.Value;
        if (ctrlName.EndsWith(".ascx"))
        {
            PlaceHolder1.Controls.Add(Page.LoadControl(ctrlName));
        }
        PanelLabel1.Text = "Загружено..." + ctrlName;
    }

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

Но, самое главное, поскольку эти элементы управления загружаются при запуске события Page.Load, объекты элемента управления могут обрабатывать собственные события. В этом можно удостовериться, загрузив пользовательский элемент управления TimeDisplay, а затем щелкнув на ссылке, чтобы обновить значение времени.

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

Пройди тесты
Лучший чат для C# программистов