Получение данных из динамически созданного элемента управления на панели asp:

В настоящее время я пытаюсь создать веб-мастер. У меня есть страница мастера, которая содержит кнопки навигации и панель asp, которая будет содержать отдельные панели мастера.

<asp:Panel ID="wizardControlPanel" runat="server">
   <!-- Wizard panel goes here  -->
</asp:Panel>
<asp:Button ID="backButton" runat="server" Text="&lt; Back" OnClick="BackButton_Click" />
<asp:Button ID="nextButton" runat="server" Text="Next &gt;" OnClick="NextButton_Click" />
<asp:Button ID="cancelButton" runat="server" Text="Cancel" PostBackUrl="~/"/>

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

<asp:Label ID="Title" runat="server" Text=""></asp:Label>
<asp:Label ID="DescriptionLabel" runat="server" Text ="Description for the wizard"></asp:Label>    
<asp:CheckBoxList ID="ProjectSelector" runat="server" DataTextField="ProjectName" DataValueField="Id" ></asp:CheckBoxList>

Я динамически загружаю этот элемент управления в мой wizardControlPanel после установки флажка.

WizardControl = (BaseWizardControl)LoadControl(("~/Views/" + e.ControlType.Name + ".ascx"));
wizardControlPanel.Controls.Add(WizardControl);

Проблема в; при обратной передаче мне нужно иметь возможность узнать, какие флажки были отмечены на стороне сервера, но элемент управления больше не существует. Я не могу найти его в переменной _page. Я столкнулся с проблемами (я думаю), потому что я добавляю элемент управления к держателю контента. Как я могу вернуть этот контроль?

3 ответа

Если вы динамически добавляете элементы управления в ASP.NET WebForms, вам необходимо повторно добавить их вручную в самом начале жизненного цикла страницы PostBack (например, путем переопределения OnInit и создание элемента управления с тем же идентификатором в этом коде), чтобы иметь возможность получить значения. Смотрите эту ссылку для How-To.

В следующем примере показаны основные шаги. Он состоит из ASPX-страницы, которая содержит Panel в качестве заполнителя:

<asp:Panel ID="wizardPanel" runat="server">
</asp:Panel>
<asp:Button ID="btn" runat="server" Text="Do a postback" />
<br />
<asp:Label ID="lbl" runat="server" />

Это код-файл:

public partial class DynamicUserControls : System.Web.UI.Page
{
    protected UserControl userCtrl;
    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        if (Page.IsPostBack)
            CreateUserControl();
    }
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
            CreateUserControl();
        else
        {
            lbl.Text = "The following values were selected: " + string.Join(", ", ((IGetSelectedValues)userCtrl).SelectedValues);
        }
    }

    private void CreateUserControl()
    {
        if (Request["UserCtrl"] == "A")
        {
            userCtrl = (UserControl) LoadControl("~/MyUserControlA.ascx");
            userCtrl.ID = "myUserCtrl";
            wizardPanel.Controls.Add(userCtrl);
        }
        else if (Request["UserCtrl"] == "B")
        {
            userCtrl = (UserControl)LoadControl("~/MyUserControlB.ascx");
            userCtrl.ID = "myUserCtrl";
            wizardPanel.Controls.Add(userCtrl);
        }
    }
}

Основные шаги следующие:

  1. Страница определяет тип пользовательского элемента управления, который будет создан на основе параметра Request во время Page_Load (или позже, если необходимо). Он назначает идентификатор myUserCtrl в пользовательский контроль.
  2. После PostBack страница снова проверяет параметры запроса и заново создает UserControl с тем же идентификатором. myUserCtrl, Это важно для того, чтобы ASP.NET мог получать новые значения элемента управления из данных обратной передачи после фазы инициализации страницы. Самое сложное - это решить, какие пользовательские элементы управления создать, потому что данные, доступные в OnInit обычно не слишком много.
  3. В Page_Loadпользовательский элемент управления может быть доступен, и значения, которые были отправлены обратно, доступны. UserControls в образце содержат CheckBoxList и реализуют интерфейс, который позволяет получать значения, выбранные пользователем.

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

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

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

Как говорит Маркус, возможно, есть лучший способ сделать то, что вы пытаетесь сделать. Но если вы ДОЛЖНЫ загрузить это динамически, это то, как вы должны найти его.

Я искал не в том месте. Page.Form в отличие от Page.Request.Form. Поскольку контрольный список уже определен в пользовательском элементе управления, его имя прослеживается в этой переменной. Таким образом, я могу сохранить текущую структуру мастера.

Другие вопросы по тегам