Обработчик событий не запускается для динамически созданных элементов управления - PullRequest
9 голосов
/ 21 ноября 2008

У меня проблема с динамически создаваемым TextBox.

Когда TextBox создается в PageLoad, происходит событие TextChanged.
Но когда я динамически удалял и заново создавал TextBox, TextChanged не запускался.

Это код:

.aspx file

<body>
    <form id="form1" runat="server">
    <div>

    <asp:Table ID="Table1" runat="server">
      <asp:TableRow>
        <asp:TableCell ColumnSpan="2">Fixed content</asp:TableCell>
      </asp:TableRow>
    </asp:Table>   
    </form>
</body>

.cs file

public partial class test : System.Web.UI.Page
{
  string myText = "a";

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

  private void WriteRows()
  {
    TableRow tr = new TableRow();

    TableCell tc = new TableCell();
    TextBox txt = new TextBox();
    txt.Text = myText;
    txt.TextChanged += new EventHandler(txt_TextChanged); // Assign event handler
    tc.Controls.Add(txt);
    tr.Controls.Add(tc);

    tc = new TableCell();
    tc.Text = txt.Text;
    tr.Controls.Add(tc);

    Table1.Controls.AddAt(1, tr);
  }

  private void txt_TextChanged(object sender, EventArgs e)
  {
    myText = ((TextBox)sender).Text;
    RedrawTable(); // Delete the row (incl. the TextBox) and rewrite it
  }

  private void RedrawTable()
  {
    Table1.Controls.RemoveAt(1);
    WriteRows();
  }
}

У кого-нибудь есть решение, чтобы событие всегда срабатывало?

Ответы [ 11 ]

11 голосов
/ 21 ноября 2008

Обработка событий выполняется ASP.NET путем сопоставления идентификатора элемента управления и параметров запроса. В вашем случае TextBox, созданный во время txtTextChanged (), будет иметь автоматический идентификатор, потому что вы не указываете явный идентификатор. Этот идентификатор будет опубликован во время события изменения текста.

После события загрузки страницы ASP.NET попытается найти элемент управления с таким идентификатором, чтобы запустить событие для него. Очевидно, ASP.NET не сможет найти совпадение, потому что TextBox, созданный во время Page_Load (), отличается и имеет другой идентификатор.

Чтобы решить эту проблему: укажите явный идентификатор для вашего текстового поля:

TextBox txt = new TextBox();
txt.Text = myText;
txt.ID = "txtBox";
3 голосов
/ 21 ноября 2008

Попробуйте создать элементы управления в методе Page_Init () ...

2 голосов
/ 23 ноября 2008

Повторно создайте динамически созданные элементы управления в Page_Init. У вас не будет доступа к данным viewstate элемента управления, если вы заново создадите их в Page_Load (viewstate загружается в PreLoad, что происходит до Page_Load).

Кроме того, не забудьте присвоить ID элементу управления.

2 голосов
/ 21 ноября 2008

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

Если у вас есть статические элементы управления (определенные в aspx / ascx / master) и viewstate, то они будут воссозданы автоматически.

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

если вы измените идентификатор родительского элемента управления или страницы, вы можете случайно сбросить автосвязку состояния представления, поскольку идентификаторы элемента управления содержат идентификаторы предков. Я думаю, что вы должны делать это безопасно, если вы делаете это в Page_Init (до настройки viewstate)

1 голос
/ 21 ноября 2008

У меня была похожая проблема. Я думаю, что проблема заключается в том, что динамически созданные элементы управления не сохраняются в состоянии просмотра и не переносят обратную передачу. Вот комментарий, скопированный из моего кода, который описывает решение, которое я придумал (возможно, оно не единственное, но у меня это сработало).

Эта страница используется для динамического определения сетки. Пользователь нажимает флажки указать, какие поля включить в сетку. Логика этой страницы делает две важные вещи:

(1) Он поддерживает объект GridDefinition, который хранится в ViewState. (2) Он реконструирует программно добавленные элементы управления (по существу, все в объекте таблицы) из GridDefinition в ViewState при каждой обратной передаче. Динамически добавленные элементы управления НЕ воссоздаются при обратной передаче из ViewState. Действительно, я обнаружил, что если вы не создадите заново элементы управления, их события не сработают. По-видимому:

       "The process that matches controls to posted values occurs 
       after page_load completes, so it has to occur just like this 
       if you are to use this way."

Когда я получаю контрольное событие, указывающее на некоторые изменения в данных, я должен отразить это изменение в объекте GridDefinition, хранящемся в ViewState. Таким образом, на СЛЕДУЮЩЕМ После обратной передачи элемент управления может быть воссоздан должным образом (например, текстовое поле, указывающее текст заголовка для столбца сетки).

0 голосов
/ 29 июля 2014

У меня была такая же проблема, и в моем случае txt.AutoPostBack = true было то, что я пропустил. Значение по умолчанию - false, его легко забыть.

0 голосов
/ 14 ноября 2010

Вам нужно будет просто назначить свойство идентификатора с помощью текстового поля. Это должно решить вашу проблему.

0 голосов
/ 28 мая 2010

Ваш ответ приведен ниже с полным кодом:

string myText = "a";

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

private void WriteRows()
{
    TableRow tr = new TableRow();

    TableCell tc = new TableCell();
    TextBox txt = new TextBox();
    txt.Text = myText;

    txt.ID = "txt1";

    txt.TextChanged += new EventHandler(txt_TextChanged); // Assign event handler

    txt.AutoPostBack = true;

    tc.Controls.Add(txt);
    tr.Controls.Add(tc);

    tc = new TableCell();
    tc.Text = txt.Text;
    tr.Controls.Add(tc);

   Table1.Controls.AddAt(0,tr);

}

private void txt_TextChanged(object sender, EventArgs e)
{
    myText = ((TextBox)sender).Text;
    RedrawTable(); // Delete the row (incl. the TextBox) and rewrite it
}

private void RedrawTable()
{
    Table1.Controls.RemoveAt(0);
    WriteRows();
}
0 голосов
/ 21 ноября 2008

Мне еще раз напомнили, почему я избегаю аспа - мне кажется, что один уровень абстракции слишком много. Но, по аналогии с javascript, возможно, у вас получилось более одного обработчика события?

0 голосов
/ 21 ноября 2008

... как еще одно предположение, не связывает ли события после Page_Load слишком поздно? и поэтому они не будут уволены с обратной передачи. может быть, что-то проверить ..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...