C# 加载页面后插入动态控件(ViewState持久)

C# 加载页面后插入动态控件(ViewState持久),c#,controls,viewstate,persistent,C#,Controls,Viewstate,Persistent,我在一个页面中创建了一个动态表,其中包含引发事件的动态控件。 它可以工作,但我不想在某些事件中重新生成该表(所以在页面加载后)以打印表修改 我理解这个问题,因为我的控件是在页面加载之后创建的,并且没有引发事件,所以此时,我的控件没有持久化到viewstate中。但我怎么能做到这一点呢 这是我的密码: protected void Page_Load(object sender, EventArgs e) { generateTable(); // When pass just here,

我在一个页面中创建了一个动态表,其中包含引发事件的动态控件。 它可以工作,但我不想在某些事件中重新生成该表(所以在页面加载后)以打印表修改

我理解这个问题,因为我的控件是在页面加载之后创建的,并且没有引发事件,所以此时,我的控件没有持久化到viewstate中。但我怎么能做到这一点呢

这是我的密码:

protected void Page_Load(object sender, EventArgs e)
{
    generateTable(); // When pass just here, it works well
}

private void generateTable()
{
    Table tbl = new Table();
    // Here I create my table with controls

    tableContainer.Controls.Clear(); // tableContainer is a Panel fixed in aspx page
    tableContainer.Controls.Add(tbl);
}

protected void txt_TextChanged(object sender, EventArgs e)
{
    // Do some stuff to change values in the table
    generateTable(); // Re-generate (but events will not be raised)
}
更新1:

我考虑过一些事情(这会使我的开发复杂化),但我应该做generateTable,它会创建我所有的行和控件,并在每个页面加载时调用它。另一方面,创建另一个填充控件的方法?所以在事件中,我称之为第二个


但是我的表是动态生成的,控件也可以在事件之后添加(我有一个dropdownlist,它在表中创建了一个新行和控件,所以我也被困在这里,因为我在第一次回发时看不到该行?

您应该在PageInit事件上生成控件。在PageInit上生成的控件由asp.net框架自动管理(您将获得viewstate持久性、引发的事件等)

请注意:在PageInit上,您必须始终重新生成动态控件,否则框架将无法管理它们

尝试在PageInit上生成控件,然后在回发事件中更改它们的属性,如下所示:

List<LiteralControl> list = new List<LiteralControl>();

protected void Page_Init(object sender, EventArgs e)
{
    generateTable(); // When pass just here, it works well
}

private void generateTable()
{
    Table tbl = new Table();
    // Here I create my table with controls

    int rows = 3;
    int cols = 2;
    for (int j = 0; j < rows; j++)
    {
        TableRow r = new TableRow();
        for (int i = 0; i < cols; i++)
        {
            TableCell c = new TableCell();
            LiteralControl l = new LiteralControl("row " + j.ToString() + ", cell " + i.ToString());

            // save a reference to the control for editing
            list.Add(l);

            c.Controls.Add(l);
            r.Cells.Add(c);
        }
        tbl.Rows.Add(r);
    }

    tableContainer.Controls.Clear(); // tableContainer is a Panel fixed in aspx page
    tableContainer.Controls.Add(tbl);
}

protected void txt_TextChanged(object sender, EventArgs e)
{
    // edit controls here
    foreach (LiteralControl ctrl in list)
    {
        ctrl.Text = "TextChanged";
    }
}
List List=新列表();
受保护的无效页_Init(对象发送方,事件参数e)
{
generateTable();//当在此处传递时,它工作得很好
}
私有void generateTable()
{
表tbl=新表();
//在这里,我创建了带有控件的表
int行=3;
int cols=2;
对于(int j=0;j
您应该在PageInit事件上生成控件。在PageInit上生成的控件由asp.net框架自动管理(您将获得viewstate持久性、引发的事件等)

请注意:在PageInit上,您必须始终重新生成动态控件,否则框架将无法管理它们

尝试在PageInit上生成控件,然后在回发事件中更改它们的属性,如下所示:

List<LiteralControl> list = new List<LiteralControl>();

protected void Page_Init(object sender, EventArgs e)
{
    generateTable(); // When pass just here, it works well
}

private void generateTable()
{
    Table tbl = new Table();
    // Here I create my table with controls

    int rows = 3;
    int cols = 2;
    for (int j = 0; j < rows; j++)
    {
        TableRow r = new TableRow();
        for (int i = 0; i < cols; i++)
        {
            TableCell c = new TableCell();
            LiteralControl l = new LiteralControl("row " + j.ToString() + ", cell " + i.ToString());

            // save a reference to the control for editing
            list.Add(l);

            c.Controls.Add(l);
            r.Cells.Add(c);
        }
        tbl.Rows.Add(r);
    }

    tableContainer.Controls.Clear(); // tableContainer is a Panel fixed in aspx page
    tableContainer.Controls.Add(tbl);
}

protected void txt_TextChanged(object sender, EventArgs e)
{
    // edit controls here
    foreach (LiteralControl ctrl in list)
    {
        ctrl.Text = "TextChanged";
    }
}
List List=新列表();
受保护的无效页_Init(对象发送方,事件参数e)
{
generateTable();//当在此处传递时,它工作得很好
}
私有void generateTable()
{
表tbl=新表();
//在这里,我创建了带有控件的表
int行=3;
int cols=2;
对于(int j=0;j
这里有一个非常好的链接,介绍了动态添加控件的管理:

请注意,在ASP.NET后端的任意位置添加控件后,必须设置属性

ViewState["AddedControl"] = "true";
此外,在回发期间,将重新生成页面,因此此时必须重新创建控件并设置旧值

从同一链接:

public void Page_Load() {
   if (IsPostBack) {
      if (ViewState["AddedControl"] != null) {
         // Re-create the control but do not
         // restore settings configured outside
         // the proc (i.e., MaxLength and BackColor)
         TextBox t = AddTextBox(); 
      }  
   }
}
public void OnClick(object sender, EventArgs e) {
   TextBox t = AddTextBox();
 
   // Modify properties outside the proc to
   // simulate generic changed to the
   // control's view state
   t.MaxLength = 5;
   t.BackColor = Color.Yellow;
}

public TextBox AddTextBox() {
   TextBox ctl = new TextBox();
   ctl.Text = "Hello";
   placeHolder.Controls.Add(ctl);
 
   // Records that a dynamic control has been added
   ViewState["AddedControl"] = "true";
   return ctl;
}

下面是一个非常好的链接,它描述了动态添加控件的管理:

请注意,在ASP.NET后端的任意位置添加控件后,必须设置属性

ViewState["AddedControl"] = "true";
此外,在回发期间,将重新生成页面,因此此时必须重新创建控件并设置旧值

从同一链接:

public void Page_Load() {
   if (IsPostBack) {
      if (ViewState["AddedControl"] != null) {
         // Re-create the control but do not
         // restore settings configured outside
         // the proc (i.e., MaxLength and BackColor)
         TextBox t = AddTextBox(); 
      }  
   }
}
public void OnClick(object sender, EventArgs e) {
   TextBox t = AddTextBox();
 
   // Modify properties outside the proc to
   // simulate generic changed to the
   // control's view state
   t.MaxLength = 5;
   t.BackColor = Color.Yellow;
}

public TextBox AddTextBox() {
   TextBox ctl = new TextBox();
   ctl.Text = "Hello";
   placeHolder.Controls.Add(ctl);
 
   // Records that a dynamic control has been added
   ViewState["AddedControl"] = "true";
   return ctl;
}

是的,但问题是在某些情况下,我必须从事件调用generateTable(),所以在Page_Init和Page_Load之后,为什么必须调用generateTable两次?你能给我举个例子吗?实际上,我的表包含一些引发事件的控件。在此事件中,我修改了存储在viewstate中的对象中的一些值,这些值将打印在表中。因此,当它在回发事件中更改时,我想在表中打印它,但我在加载页面之后,必须刷新一次屏幕才能看到它!我调用它两次,因为第一次它初始化我的控件以便引发事件,第二次它实现事件中发生的更改。刚刚看到您的编辑,它会工作,但我有一个情况,我必须在事件中添加一个控件,因此此控件不会保留在第一次postbackYes中,但问题是,在某些情况下,我必须从事件调用generateTable(),所以在Page_Init和Page_Load之后,为什么必须调用generateTable两次?你能给我举个例子吗?实际上,我的表包含一些引发事件的控件。在此事件中,我修改了ob中的一些值