У меня есть GridView с динамически созданными кнопками изображений, которые должны запускать командные события при нажатии. Обработка событий в основном работает, за исключением самого первого нажатия кнопки. Затем выполняется обратная передача, но событие не запускается.
Я попытался отладить это, и мне кажется, что код, выполняемый до и после первого клика, точно такой же, как и для любых других кликов. (За исключением того, что при первом щелчке обработчик событий не вызывается.)
В этом есть одна особенность: кнопки, запускающие событие, создаются динамически с помощью привязки данных, то есть привязка данных должна выполняться дважды в течение жизненного цикла страницы: один раз при загрузке, чтобы кнопки существовали (в противном случае события могут не обрабатывается вообще) и один раз перед рендерингом для отображения новых данных после обработки событий.
Я прочитал эти посты, но они не соответствуют моей ситуации:
Событие ASP.NET LinkButton OnClick не работает на домашней странице ,
LinkButton не работает на рабочем сервере ,
Событие ASP.NET Click () не запускается при второй обратной передаче
К деталям:
GridView содержит кнопки изображений в каждой строке. Изображения кнопок привязаны к данным. Строки создаются GridView.DataBind (). Чтобы добиться этого, я использовал TemplateField с пользовательской реализацией ItemTemplate. Метод InstantiateIn ItemTemplate создает ImageButton и назначает ему соответствующий обработчик события. Кроме того, событию DataBinding изображения назначается обработчик, который извлекает соответствующее изображение на основе данных соответствующей строки.
GridView помещается в UserControl. UserControl определяет обработчики событий для событий GridView. Код примерно выглядит следующим образом:
private DataTable dataTable = new DataTable();
protected SPGridView grid;
protected override void OnLoad(EventArgs e)
{
DoDataBind(); // Creates the grid. This is essential in order for postback events to work.
}
protected override void Render(HtmlTextWriter writer)
{
DoDataBind();
base.Render(writer); // Renews the grid according to the latest changes
}
void ReadButton_Command(object sender, CommandEventArgs e)
{
ImageButton button = (ImageButton)sender;
GridViewRow viewRow = (GridViewRow)button.NamingContainer;
int rowIndex = viewRow.RowIndex;
// rowIndex is used to identify the row in which the button was clicked,
// since the control.ID is equal for all rows.
// [... some code to process the event ...]
}
private void DoDataBind()
{
// [... Some code to fill the dataTable ...]
grid.AutoGenerateColumns = false;
grid.Columns.Clear();
TemplateField templateField = new TemplateField();
templateField.HeaderText = "";
templateField.ItemTemplate = new MyItemTemplate(new CommandEventHandler(ReadButton_Command));
grid.Columns.Add(templateField);
grid.DataSource = this.dataTable.DefaultView;
grid.DataBind();
}
private class MyItemTemplate : ITemplate
{
private CommandEventHandler commandEventHandler;
public MyItemTemplate(CommandEventHandler commandEventHandler)
{
this.commandEventHandler = commandEventHandler;
}
public void InstantiateIn(Control container)
{
ImageButton imageButton = new ImageButton();
imageButton.ID = "btnRead";
imageButton.Command += commandEventHandler;
imageButton.DataBinding += new EventHandler(imageButton_DataBinding);
container.Controls.Add(imageButton);
}
void imageButton_DataBinding(object sender, EventArgs e)
{
// Code to get image URL
}
}
Просто повторюсь: на каждом жизненном цикле сначала выполняется OnLoad, который генерирует Grid с помощью кнопок ImageButtons. Затем события обрабатываются. Поскольку кнопки есть, события обычно работают. После этого вызывается Render, который генерирует Grid с нуля на основе новых данных. Это всегда работает, за исключением самого первого раза, когда пользователь нажимает кнопку изображения, хотя я утверждал, что кнопки сетки и изображения также генерируются, когда страница отправляется пользователю в первый раз.
Надеюсь, что кто-то может помочь мне понять это или предложить лучшее решение для моей ситуации.