我有一个动态创建图像按钮的网格视图,单击时应该触发命令事件。事件处理基本上可以工作,除了第一次单击按钮。然后,将处理回发,但不会激发事件。
我试过调试它,在我看来,第一次单击之前和之后执行的代码与其他单击的代码完全相同。(除了第一次单击时不调用事件处理程序。)
其中有一些特殊之处:触发事件的按钮是通过数据绑定动态创建的,即数据绑定必须在页面生命周期中执行两次:加载一次,以便使按钮存在(否则,事件根本无法处理),渲染前执行一次,以便在EVE之后显示新数据。NTS已处理。
我读过这些帖子,但它们不符合我的情况:
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.databind()生成。为了实现这一点,我使用了一个定制的itemtemplate实现的templatefield。itemTemplate的instantain方法创建ImageButton并为其分配相应的事件处理程序。此外,将为图像的数据绑定事件分配一个处理程序,该处理程序根据相应行的数据检索适当的图像。
网格视图放置在一个用户控件上。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生成网格。然后,处理事件。因为按钮在那里,所以事件通常工作。然后,调用render,它根据新数据从头生成网格。这总是有效的,除了第一次用户单击图像按钮,尽管我已经声明网格和图像按钮也是在第一次将页面发送给用户时生成的。
希望有人能帮助我理解这一点,或者告诉我一个更好的解决方案。