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

Web-формы

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

С использованием коллекции Controls можно на лету создать и добавить к HTML-выводу любой элемент управления. Приведем пример, динамически создающий кнопку в HTML-выводе. Пусть у нас имеется код

  • Добавьте к проекту предыдущего примера новую страницу с разделенным кодом и именем DynamicButton. Сделайте страницу стартовой.
  • Поместите на страницу из вкладки Standard элемент управления Panel, метку Label, три кнопки Button, а из вкладки HTML - элемент Horizontal Rule

Настройте интерфейс страницы времени проектирования так


  • Заполните обработчик загрузки страницы следующим кодом
    public partial class DynamicButton : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // Создать новый объект кнопки
            Button newButton = new Button();
    	
            // Присвоить значения свойств
            newButton.ID = "newButton";// Пометили
            newButton.Text = "* Dynamic Button *";
    	
            // Добавить кнопку в коллекцию элементов управления формы
            form1.Controls.Add(newButton);
        }
    }
  • Запустите страницу на выполнение. Получится такой результат
    HTML-вывод страницы динамического создания кнопки

    HTML-вывод страницы динамического создания кнопки

Мы получили то, что динамически созданная кнопка оказалась в конце декскриптора <form>. Для получения большего контроля над расположением динамического элемента управления можно использовать элемент управления PlaceHolder. Целью элемента управления PlaceHolder (держатель места) является размещение других элементов управления. Если разместить элемент PlaceHolder на форме и не добавить в его коллекцию Controls других элементов, он ничего не изменит на окончательном HTML-выводе.

  • Поместите элемент управления PlaceHolder впереди кнопки с названием "Reset Text" и перепишите код так, чтобы динамически создаваемая кнопка добавлялась не в коллекцию формы, а в коллекцию PlaceHolder
    // Добавить кнопку в коллекцию PlaceHolder1
    PlaceHolder1.Controls.Add(newButton);

Теперь HTML-вывод должен быть таким

HTML-вывод страницы динамического создания кнопки

HTML-вывод страницы динамического создания кнопки

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

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

Если мы собираемся взаимодействовать с динамически созданным элементом управления дальше, то ему следует присвоить уникальный идентификатор, что мы и сделали в нашем примере. Мы можем использовать этот идентификатор для извлечения элемента управления из коллекции Controls родительского контейнера. Можно найти элемент управления с использованием рекурсивной логики поиска, как мы это делали в странице ControlTree.aspx. Можно для поиска элемента использовать статический метод Page.FindControl().

Для примера добавим функциональность к кнопке с названием Remove Button, которая будет удалять динамически созданную кнопку. Если с обратной отсылкой придет событие (сообщение), что пользователь щелкнул на кнопке Remove Button, то мы должны будем найти динамически созданную ранее в обработчике Page_Load() кнопку и удалить ее из страницы. И в уже готовящемся нашей страницей HTML-выводе этой кнопки не будет.

  • Двойным щелчком на кнопке с названием Remove Button создайте для нее обработчик, который заполните так
    protected void Button3_Click(object sender, EventArgs e)
    {
        // Поиск кнопки вне зависимости от иерархического
        // уровня, в котором она расположена
        Button foundButton = (Button)Page.FindControl("newButton");
    	
        // Удаление кнопки с проверкой условия, чтобы
        // не пытались удалить уже удаленный объект
        if (foundButton != null)
        {
            // Удаляем из коллекции родительского элемента управления
            foundButton.Parent.Controls.Remove(foundButton);
        }
    }

Следует заметить, что последний оператор приведенного кода Remove() не удаляет объект кнопки физически, а удаляет только ссылку на кнопку из коллекции PlaceHolder. Это значит, что кнопка, однажды созданная в обработчике Page_Load(), продолжает существовать в контейнере Page страницы и мы всегда можем ее использовать дальше.

Динамически добавленные элементы управления могут обрабатывать события. Нужно лишь подключить обработчик события с использованием кода-делегата. Подключать события обязательно нужно в обработчике Page_Load(), иначе будет поздно, поскольку все поступившие с обратной отсылкой события клиента генерируются сразу после события Page.Load. Если код подключения события с помощью делегата разместить в другом месте, обработчик события не сработает, поскольку система это событие уже сгенерирует и, не найдя соответствующий обработчик, оставит без внимания.

  • Добавьте в конец обработчика Page_Load() следующий код
    protected void Page_Load(object sender, EventArgs e)
    {
        // Создать новый объект кнопки
        Button newButton = new Button();
    	
        // Присвоить значения свойств
        newButton.ID = "newButton";
        newButton.Text = "* Dynamic Button *";
    	
        // Добавить кнопку в коллекцию PlaceHolder1
        PlaceHolder1.Controls.Add(newButton);
    	
        // Подключение обработчика события Button.Click
        // динамически созданного элемента управления
        newButton.Click += new EventHandler(newButton_Click);
    }
    	
    void newButton_Click(object sender, EventArgs e)
    {
        Label1.Text = "Этот текст прислал обработчик" + 
                      " динамически созданной кнопки";
    }
  • Сбросьте для метки Label1 свойство сохранения состояния вида, назначив EnableViewState=false

Окончательный вариант страницы должен быть таким

<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="DynamicButton.aspx.cs" Inherits="DynamicButton" %>
	
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Label ID="Label1" runat="server" Text="Щелкните на динамически созданной кнопке"
            Width="431px" EnableViewState="False"></asp:Label><br />
        <br />
        <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
        &nbsp;
        <asp:Button ID="Button1" runat="server" Text="Reset Text" /><br />
        <hr />
        <asp:Button ID="Button2" runat="server" Text="Create Button" />
        &nbsp;&nbsp;
        <asp:Button ID="Button3" runat="server" Text="Remove Button" OnClick="Button3_Click" />
    </div>
    </form>
</body>
</html>
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 DynamicButton : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        // Создать новый объект кнопки
        Button newButton = new Button();
	
        // Присвоить значения свойств
        newButton.ID = "newButton";
        newButton.Text = "* Dynamic Button *";
	
        // Добавить кнопку в коллекцию PlaceHolder1
        PlaceHolder1.Controls.Add(newButton);
	
        // Подключение обработчика события Button.Click
        // динамически созданного элемента управления
        newButton.Click += new EventHandler(newButton_Click);
    }
	
    void newButton_Click(object sender, EventArgs e)
    {
        Label1.Text = "Этот текст прислал обработчик" + 
                      " динамически созданной кнопки";
    }
	
    protected void Button3_Click(object sender, EventArgs e)
    {
        // Поиск кнопки вне зависимости от иерархического
        // уровня, в котором она расположена
        Button foundButton = (Button)Page.FindControl("newButton");
	
        // Удаление кнопки с проверкой условия, чтобы
        // не пытались удалить уже удаленный объект
        if (foundButton != null)
        {
            // Удаляем из коллекции родительского элемента управления
            foundButton.Parent.Controls.Remove(foundButton);
        }
    }
}
  • Запустите и испытайте закодированную страницу DynamicButton.aspx

В окне броузера мы видим, что при каждом вызове страницы динамическая кнопка создается на сервере и посылается клиенту. При нажатии кнопки Remove Button посланное на сервер событие вызывает срабатывание обработчика удаления кнопки из коллекции. Посылка данных на сервер при нажатии других незапрограммированных кнопок опять создает динамическую кнопку и добавляет ее в контейнер. Щелчок на динамической кнопке запускает обработчик смены текста в метке Label1. Щелчок на любой другой кнопке восстанавливает первоначальное содержимое метки Label1, поскольку мы сняли свойство сохранения состояния вида.

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