Вмъкване на динамични контроли след page_load (постоянен ViewState)

Имам страница, където създавам динамична таблица, съдържаща динамични контроли, които предизвикват събития. Работи, но не искам да генерирам повторно тази таблица в някои събития (така че след page_load), за да отпечатам модификациите на таблицата.

Разбирам проблема, той е, че в този момент моите контроли не се запазват в viewstate, защото са създадени след page_load и техните събития не се повдигат. Но как бих могъл да направя това?

Ето моят код:

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, който създава всичките ми редове и контроли и да го извиквам при всяко page_load. И от друга страна, създайте друг метод, който попълва контролите? Така че в събитията аз наричам втория.

Но моята таблица се генерира динамично и контролите също могат да се добавят след събитие (имам падащ списък, който създава нов ред и контрола в таблицата, така че също съм заседнал тук, защото няма да видя реда в началото обратно изпращане?)


person Guillaume Martin    schedule 04.06.2013    source източник


Отговори (2)


Ето една наистина добра връзка, която описва управлението на динамично добавени контроли: https://web.archive.org/web/20050321094957/http://devcenter.infragistics.com/Articles/ArticleTemplate.ASPX?ArticleID=2149

Обърнете внимание, че след като добавите контролата във вашия бекенд на 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;
}
person Yogee    schedule 04.06.2013
comment
Същият проблем с това, тъй като не минавам през Page_Load след моето събитие и не виждам промени преди друго обратно изпращане. - person Guillaume Martin; 04.06.2013

Вместо това трябва да генерирате вашите контроли на събитието PageInit. Контролите, генерирани на PageInit, се управляват автоматично от asp.net framework (ще получите постоянство на 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";
    }
}
person bastos.sergio    schedule 04.06.2013
comment
Да, но проблемът е, че в някои случаи трябва да извикам generateTable() от събитие, така че след Page_Init и след Page_Load - person Guillaume Martin; 04.06.2013
comment
Защо трябва да се обаждате на generateTable два пъти? Можете ли да ми дадете пример? - person bastos.sergio; 04.06.2013
comment
всъщност моята таблица съдържа някои контроли, които предизвикват събития. В това събитие променям някои стойности в обект, съхранен в viewstate, и тези стойности се отпечатват в таблицата. Така че, когато се промени при събитие за обратно изпращане, искам да го отпечатам в таблицата, но съм след page_load и ще трябва да опресня веднъж екрана, за да го видя! - person Guillaume Martin; 04.06.2013
comment
Извиквам го два пъти, защото първия път инициализира моите контроли, така че събитията да могат да бъдат повдигнати, и вторият път, за да актуализира промените, настъпили в събитието. - person Guillaume Martin; 04.06.2013
comment
Току-що видях вашата редакция, ще свърши работа, но имам случай, в който трябва да добавя контрола В събитието, така че това няма да бъде запазено в първото обратно изпращане - person Guillaume Martin; 04.06.2013
comment
Добавете контролата в метода PageInit, но я задайте невидима. След това в txt промененото събитие го задайте видимо. - person bastos.sergio; 04.06.2013