【发布时间】:2010-01-28 10:09:30
【问题描述】:
我有一个带有动态创建的图像按钮的 GridView,单击时应该触发命令事件。事件处理基本上是有效的,除了第一次单击按钮。然后,回发被处理,但事件没有被触发。
我已尝试对此进行调试,在我看来,在第一次点击之前和之后执行的代码与任何其他点击完全相同。 (除了在第一次点击时,不调用事件处理程序。)
有一些特殊性:触发事件的按钮是通过数据绑定动态创建的,即数据绑定必须在页面生命周期中执行两次:一旦加载,为了使按钮存在(否则,事件可能根本不处理),并且在渲染之前一次,以便在事件处理后显示新数据。
我已阅读这些帖子,但它们与我的情况不符: ASP.NET LinkButton OnClick Event Is Not Working On Home Page, LinkButton not firing on production server, ASP.NET Click() event doesn't fire on second postback
到细节: GridView 在每一行中都包含图像按钮。按钮的图像是数据绑定的。行由 GridView.DataBind() 生成。为此,我使用了带有自定义 ItemTemplate 实现的 TemplateField。 ItemTemplate 的 InstantiateIn 方法创建 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,它会生成带有 ImageButtons 的 Grid。然后,处理事件。由于按钮在那里,事件通常有效。之后,调用 Render,它会根据新数据从头开始生成 Grid。这总是有效的,除了用户第一次点击图像按钮,虽然我已经断言当页面第一次发送给用户时也会生成网格和图像按钮。
希望有人能帮助我理解这一点或告诉我一个更好的解决方案。
【问题讨论】:
标签: asp.net data-binding gridview event-handling postback