ASP.NET动态添加控件和页面生命周期

时间:2014-04-04 15:15:49

标签: asp.net web-controls

我是ASP.NET的新手,所以请耐心等待。

以下是我的方案的简要说明。我在页面上有一个按钮。当我单击按钮时,我将从数据库中检索字符串列表,并动态生成一系列链接按钮,并将检索到的字符串作为链接按钮的文本。

我已经明白,由于多种原因,我无法在按钮的点击事件处理程序中执行此操作。我也明白动态控件需要在Page_Init或Page_Load事件处理程序中生成,以便链接按钮能够生成。点击事件可以连线。

所以,这是我考虑的过程:

  1. 点击按钮
  2. 在click事件处理程序中,检索字符串并将它们存储在ViewState变量
  3. 在Page_Load事件处理程序中,遍历ViewState变量中的字符串并生成链接按钮
  4. 问题在于:由于页面的生命周期,按钮的点击事件直到Page_Load事件之后才会被处理。因此,用于生成链接按钮的字符串不会被检索并分配给ViewState变量,直到在Page_Load事件之后(我希望创建链接按钮的位置)。

    因此,在分配ViewState变量时,直到第二次单击按钮时才会生成链接按钮。显然,这是一个问题。

    我设计的解决方案有效,但我不知道它是否是最佳解决方案。以下是我使用的方法:

    1. 点击按钮
    2. Page_Load事件触发
    3. 在Page_Load事件处理程序中,如果它是一个PostBack检查以查看ViewState变量是否为null以及哪个控件触发了PostBack
    4. 如果ViewState变量为null并且单击了Button,则检索字符串,将它们保存到ViewState变量,并根据ViewState变量生成链接按钮
    5. 如果ViewState变量不为null,则根据ViewState变量生成链接按钮
    6. 现在,这个解决方案确实有效。但是,如果我刷新页面,我会收到确认表单重新提交弹出窗口(我不喜欢,但我可以忍受)。

      我对这里的编码人员的问题是 - 你将如何处理我的情况?

      更新:

      这是一个似乎有效的解决方案。我可能对事件处理程序可以连线的地方感到困惑,但是请看看这段代码并告诉我它是否有意义或者它是否只是一个黑客:

      public partial class _Default : System.Web.UI.Page
      {
          protected void Page_Load(object sender, EventArgs e)
          {
              if (IsPostBack)
              {
                  if(ViewState["ControlsArray"] != null)
                  {
                      ArrayList controlsList = (ArrayList)ViewState["ControlsArray"];
                      GenerateLinkButtons(controlsList);
                  }
              }
          }
      
          //The event handler for the dynamically generated linkbuttons
          void linkButton_Click(object sender, EventArgs e)
          {
              LinkButton btn = (LinkButton)sender;
              string btnName = btn.Text;
      
              Response.Write(btnName);
          }
      
          //The click event handler for the Generate Controls button
          protected void Button1_Click(object sender, EventArgs e)
          {
              ArrayList PageArrayList = new ArrayList();
      
              PageArrayList = new ArrayList();
              PageArrayList.Add("Text 1");
              PageArrayList.Add("Text 2");
              PageArrayList.Add("Text 3");
              PageArrayList.Add("Text 4");
              PageArrayList.Add("Text 5");
      
              GenerateLinkButtons(PageArrayList);
      
              ViewState["ControlsArray"] = PageArrayList;
          }
      
          void GenerateLinkButtons(ArrayList controlsList)
          {
              int i = 1;
      
              foreach (string s in controlsList)
              {
                  LinkButton lnkButton = new LinkButton();
                  lnkButton.ID = "btn" + i;
                  lnkButton.Text = s;
                  this.form1.Controls.Add(lnkButton);
                  this.form1.Controls.Add(new LiteralControl("<br />"));
                  lnkButton.Click += new EventHandler(linkButton_Click);
                  i++;
              }
          }
      }
      

1 个答案:

答案 0 :(得分:2)

  

需要在Page_Init或Page_Load事件处理程序中生成动态控件,以便链接按钮“点击事件可以连线。

实际上,您可以在Button Click事件上创建控件。但您必须确保在以下PostBack中重新创建这些控件。

因此,假设您有一个名为Data的属性,它指向一个ViewState变量。我们还假设您使用Repeater来创建LinkBut​​tons。

然后你可以这样做:

private List<string> Data
{
    get { return (List<string>)ViewState["Data"]; }
    set { ViewState["Data"] = value; }
}

protected void Button_Click(object sender, EventArgs e)
{
    Data = GetData();
    LoadRepeater();
}

protected void Page_Load(object sender, EventArgs e)
{
    if(Data != null)
    {
        LoadRepeater();
    }
}

private void LoadRepeater()
{
    repeater.DataSource = Data;
    repeater.DataBind();
}

中继器:

<asp:Repeater id="repeater" runat="server">
    <ItemTemplate>
        <asp:LinkButton id="link" runat="server" OnClick="link_Click" />
    </ItemTemplate>
</asp:Repeater>

protected void link_Click(object sender, EventArgs e)
{
    //Do Stuff
}

此外,如果要避免使用Confirm Form Resubmission,请使用ASP.NET UpdatePanel控件。 例如:

<asp:UpdatePanel id="upp" runat="server" >
    <ContentTemplate>
        <!-- Button-->
        <!-- Repeater-->
        <!-- Other Stuff-->
    </ContentTemplate>
</asp:UpdatePanel>

另一种方法(不确定是否有效):

尝试在标签定义上设置转发器DataSource:

<asp:Repeater id="repeater" runat="server" DataSource='<%# Data %>' >
    <ItemTemplate>
        <asp:LinkButton id="link" runat="server" OnClick="link_Click" />
    </ItemTemplate>
</asp:Repeater>

protected void Button_Click(object sender, EventArgs e)
{
    Data = GetData();
    LoadRepeater();
}

protected void Page_Load(object sender, EventArgs e)
{
}

private void LoadRepeater()
{
    repeater.DataBind();
}