从asp:面板中的动态创建的控件中获取数据

时间:2016-02-17 12:45:30

标签: c# asp.net postback wizard dynamic-controls

我目前正在尝试创建基于Web的向导工具。我有一个向导页面,其中包含导航按钮和一个包含各个向导面板的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 个答案:

答案 0 :(得分:1)

如果在ASP.NET WebForms中动态添加控件,则需要在PostBack的页面生命周期中尽早手动重新添加它们(例如,通过覆盖OnInit并在此处创建具有相同id的控件代码)以便能够检索值。有关操作方法,请参阅此link

以下示例显示了基本步骤。它由一个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" />

这是codebehind-file:

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. 该页面确定在Page_Load期间(或必要时稍后)在Request参数上创建的用户控件类型。它将ID myUserCtrl分配给UserControl。
  2. 在PostBack上,页面再次检查Request参数并重新创建具有相同ID myUserCtrl的UserControl。这很重要,以便ASP.NET可以在页面初始化阶段之后从回发数据中检索控件的新值。最难的部分通常是决定要创建哪些用户控件,因为OnInit中可用的数据通常不会太多。
  3. Page_Load中,可以访问用户控件,并且可以返回已回发的值。示例中的UserControl包含CheckBoxList并实现一个允许检索用户选择的值的接口。
  4. 在大多数情况下,更容易找到不同的方法。也许您可以为包含向导页面的UserControls的向导使用MultiView控件作为静态内容。有关如何使用MultiView控件的说明,请参阅此链接。如果没有太多(读取无限)不同的UserControls使用,这种方法会更加稳定。

答案 1 :(得分:1)

就在那里,您将无法使用ID访问它。您需要通过查看wizardControlPanel.Controls集合找到它。我认为有一个属性代表您使用的文件名。但最好使用调试器来跟踪它在集合中的位置或者可以用来查找它的标识符。

完成这一次或两次之后,我想我还记得你需要在生命周期的OnLoad事件之前重新创建控件,以便回发能够填充它。

正如马库斯所说,可能有更好的方法来做你想要做的事情。但是如果你必须动态加载它,那么你应该如何定位它。

答案 2 :(得分:0)

我在找错了地方。 Page.Form而不是Page.Request.Form。由于已经在用户控件中定义了checkboxlist,因此它的名称在此变量中是可跟踪的。这样我就可以保持当前的向导结构。