Сначала мне нужно сгенерировать кнопки на основе довольно интенсивного поиска процессора и диска. Каждая кнопка представляет выбор и запускает обратную передачу. Моя проблема в том, что обратная передача не запускает команду b_Command. Я предполагаю, потому что оригинальные кнопки не были воссозданы. Я не могу позволить себе выполнить исходный поиск в обратной передаче, чтобы воссоздать кнопки, поэтому я хотел бы сгенерировать требуемую кнопку из информации обратной передачи.
Как и где мне это делать? Стоит ли делать это, например, до Page_Load? Как я могу воссоздать CommandEventHandler из обратной передачи - если вообще?
namespace CloudNavigation
{
public partial class Test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
// how can I re-generate the button and hook up the event here
// without executing heavy search 1
}
else
{
// Execute heavy search 1 to generate buttons
Button b = new Button();
b.Text = "Selection 1";
b.Command += new CommandEventHandler(b_Command);
Panel1.Controls.Add(b);
}
}
void b_Command(object sender, CommandEventArgs e)
{
// Execute heavy search 2 to generate new buttons
Button b2 = new Button();
b2.Text = "Selection 2";
b2.Command += new CommandEventHandler(b_Command);
Panel1.Controls.Add(b2);
}
}
}





Подключен ли к вашему ASPX обработчик событий?
<asp:Button id = "btnCommand" runat = "server" onClick = "b_Command" text = "Submit" />
Кнопки должны быть созданы до событие загрузки, иначе состояние не будет правильно подключено. Вместо этого воссоздайте свои кнопки в Init ().
Что касается того, как это сделать без повторного запуска поиска, я предлагаю вам где-нибудь кэшировать результаты. Наличие набора результатов в кеше - это то, как код вашей кнопки в событии Init () узнает, что его нужно запустить.
Как вариант, вы можете разместить кнопки на странице статически. Просто положите туда достаточно, чтобы обработать все, что вернет поиск. Если вы думаете, что путь может оказаться слишком большим количеством элементов, спросите себя: действительно ли ваши пользователи захотят отсортировать такое количество элементов? Возможно, вам стоит подумать о разбиении этих данных на страницы, и в этом случае статические кнопки больше не имеют большого значения.
Я согласен с Джоэлом по поводу кеширования результатов поиска. Что касается кнопок, вы можете создавать их динамически на этапах инициализации или загрузки жизненного цикла страницы, но имейте в виду, что если вы удалите кнопку, а затем добавите ее обратно программно, вы испортите свое состояние.
В одном из моих проектов у нас есть динамическая форма, которая генерирует field son the fly, и мы заставляем ее работать через массив, который хранится в кеше или в состоянии просмотра страницы. Массив содержит кнопки для отображения, и при каждой загрузке страницы он воссоздает кнопки, чтобы в них можно было правильно загрузить состояние. Затем, если мне нужно больше кнопок или совершенно новый набор, я отмечаю значение скрытия в массиве и добавляю новый набор значений в массив для нового набора соответствующих кнопок. Таким образом, состояние не теряется, и кнопки продолжают работать.
Вам также необходимо убедиться, что вы добавили обработчик для события on_click для ваших кнопок, если вы создаете их программно, что, как мне кажется, я вижу в вашем коде вверху.
Что происходит, когда обработка события обратной передачи пытается найти элемент управления, которого нет в коллекции. Касса Денис DynamicControlsPlaceholder @ http://www.denisbauer.com/ASPNETControls/DynamicControlsPlaceholder.aspx
Надеюсь, это поможет Бруно Фигейредо http://www.brunofigueiredo.com
Вот пример с настраиваемой обработкой состояния просмотра (обратите внимание, что кнопки имеют EnableViewState = false):
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Execute heavy search 1 to generate buttons
ButtonTexts = new ButtonState[] {
new ButtonState() { ID = "Btn1", Text = "Selection 1" }
};
}
AddButtons();
}
void b_Command(object sender, CommandEventArgs e)
{
TextBox1.Text = ((Button)sender).Text;
// Execute heavy search 2 to generate new buttons
ButtonTexts = new ButtonState[] {
new ButtonState() { ID = "Btn1", Text = "Selection 1" },
new ButtonState() { ID = "Btn2", Text = "Selection 2" }
};
AddButtons();
}
private void AddButtons()
{
Panel1.Controls.Clear();
foreach (ButtonState buttonState in this.ButtonTexts)
{
Button b = new Button();
b.EnableViewState = false;
b.ID = buttonState.ID;
b.Text = buttonState.Text;
b.Command += new CommandEventHandler(b_Command);
Panel1.Controls.Add(b);
}
}
private ButtonState[] ButtonTexts
{
get
{
ButtonState[] list = ViewState["ButtonTexts"] as ButtonState[];
if (list == null)
ButtonTexts = new ButtonState[0];
return list;
}
set { ViewState["ButtonTexts"] = value; }
}
[Serializable]
class ButtonState
{
public string ID { get; set; }
public string Text { get; set; }
}
Метод обработчика событий b_Command не выполняется, потому что кнопки обратной отправки не воссоздаются (поскольку они генерируются динамически). Вам нужно воссоздавать их каждый раз, когда ваша страница воссоздается, но для этого вам нужно явно кэшировать информацию где-то в состоянии.
Если это операция на уровне страницы, самый простой способ - сохранить ее в ViewState (в виде строк - если вы начнете загружать ViewState с объектами, вы увидите, что производительность снизится), чтобы вы могли проверить ее при следующей загрузке (или любой другой предыдущей. событие) и воссоздайте кнопки при перезагрузке страницы. Если операция привязана к сеансу, вы можете легко сохранить объект (массив или что-то еще) в сеансе и получить его при следующей загрузке (или инициализации) для воссоздания ваших элементов управления.
Этот сценарий означает, что вам нужно просто сохранить некоторую информацию о вашей кнопке в вашем b_Command EventHandler вместо создания и добавления кнопок, поскольку в этом случае вы потеряете относительную информацию при следующей обратной передаче (как это происходит сейчас).
так что ваш код станет чем-то вроде:
namespace CloudNavigation
{
public partial class Test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
this.recreateButtons();
}
else
{
// Execute heavy search 1 to generate buttons
Button b = new Button();
b.Text = "Selection 1";
b.Command += new CommandEventHandler(b_Command);
Panel1.Controls.Add(b);
//store this stuff in ViewState for the very first time
}
}
void b_Command(object sender, CommandEventArgs e)
{
//Execute heavy search 2 to generate new buttons
//TODO: store data into ViewState or Session
//and maybe create some new buttons
}
void recreateButtons()
{
//retrieve data from ViewState or Session and create all the buttons
//wiring them up to eventHandler
}
}
}
Если вы не хотите вызывать RecreateButtons при загрузке страницы, вы можете сделать это в PreLoad или в событиях Init, я не вижу разницы, так как вы сможете получить доступ к переменным ViewState / Session везде (в Init состояние просмотра не применяется но вы можете получить к нему доступ, чтобы воссоздать свои динамические кнопки).
Кто-то возненавидит это решение, но, насколько я знаю, единственный способ сохранить данные о состоянии на стороне сервера - это ViewState - Сессия - Page.Transfer или файлы cookie на стороне клиента.