2009-05-12 6 views
2

Я добавляю управление LinkButton динамически в PlaceHolder. Если я добавлю новый экземпляр LinkButton для каждого OnInit(), то обработчик OnClick для этого LinkButton будет работать.ASP.NET Динамически добавлено LinkButton - обработчик OnClick не называется

Однако, если я храню экземпляр LinkButton в сеансе и затем добавляю его в коллекцию элементов управления PlaceHolder, LinkButton.OnClick не запускается.

Есть ли способ повторного использования элементов управления, которые я храню в сеансе в данном сценарии? Воспроизведение их каждый раз вряд ли является вариантом.

Как примечание стороны - это унаследованное приложение в 1.1, которое я только что перенесло на 3.5. «Сломанный» подход, похоже, работает в 1.1.

Спасибо за все ответы.

public static void Clicked(object sender, EventArgs e) { 
    Debugger.Break(); 
} 

protected override void OnPreInit(EventArgs e) { 
    base.OnPreInit(e); 
    InitLinkButton(); 
} 

private void InitLinkButton() {  
    var lb = new LinkButton(); 
    plOne.Controls.Add(lb); 
    lb.ID = "lb"; 
    lb.Text = "I will work."; 
    lb.Click += Clicked; 
    plOne.Controls.Add(lb); 

    LinkButton lb2 = null; 
    if (Session["lb2"] == null) { 
     lb2 = new LinkButton(); 
     lb2.ID = "lb2"; 
     lb2.Text = "I won't work."; 
     lb2.Click += Clicked; 
     Session["lb2"] = lb2; 
    } else { 
     lb2 = (LinkButton)Session["lb2"]; 
    } 
    plOne.Controls.Add(lb2); 
} 

ответ

10

Пара вещей:

1) Никогда, никогда, никогда не храните экземпляр WebControl в сессии. Каждый WebControl имеет ссылку на объект Page - который, конечно, ссылается на каждый другой WebControl. Как только вы запустили WebControl в сеанс, вы в основном сохраняете всю страницу и все, что она содержит. Вы находитесь на шоссе в город утечки памяти.

2) Каждый элемент управления воссоздается при каждой обратной передаче. Я думаю, вы можете подумать, что повторное создание LinkButtons происходит медленно, но это неверно.

3) Почему вы не воссоздаете свои динамические элементы управления при обратной передаче? Это то, что вы должны делать с динамическими элементами управления. Вся идея состоит в том, что вы настроили страницу так же, как и она, чтобы ViewState можно было подключить к вашим элементам управления автоматически на основе их идентификаторов. Если вы попытаетесь добавить элементы управления на свою страницу динамически где-нибудь после Init(), вы не сможете использовать ViewState для обработки ваших управляющих данных и вам придется реализовать свой собственный механизм.

Моя рекомендация - воссоздать динамические элементы управления в Init() - это лучшая практика.

+1

Элементы управления в вашем .aspx воссоздаются при каждой обратной передаче. Динамические элементы управления _must_ воссоздаются при каждой обратной передаче. –

1

Вы должны также проверить dynamic controls placeholder, который поможет занять много обезьян работы из управления динамического контроля

1

Это действительно ужасная идея, чтобы сохранить LinkButton в сессии. Я даже не могу представить проблемы, которые могут возникнуть. По крайней мере, LinkButton имеет ссылку (через обработчик Clicked) на страницу, которая больше не должна существовать (страница была отображена и отправлена ​​клиенту). Но ссылка сохранит его, чтобы он не был GC'ed.

Это, как говорится, это возможный, что вам просто нужно перемонтировать обработчик вызовов:

if (Session["lb2"] == null) { 
    /* ... */ 
} else { 
    lb2 = (LinkButton)Session["lb2"]; 
    lb2.Click += Clicked; 
} 

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

Если вы используете это, вы также должны отказаться от подписки на Page_PreRender или что-то, чтобы избежать проблемы с GC.

И создание контроля снова является нормальным способом для этого - и это жизнеспособный вариант для всех остальных, поэтому вы можете переусердствовать в этом осложнениях.

3

Чтобы ответить на вопрос, как заставить OnClick работать, вам необходимо подключить событие к методу;

lb2.Click += new EventHandler(Clicked); 

Я просто не вижу проблемы с воссозданием элемента управления при инициализации, не переусердствуйте! Достаточно сказано о том, что вы храните в своей сессии, поэтому я не буду публиковать другой ответ, касающийся этой проблемы.