我有一个嵌套在GridView中的GridView。 GridView可以很好地处理绑定在其数据源中的所有实体。
我的gridview中的每条记录都有两个按钮 - “删除”和“编辑”。我遇到的问题是连接到每个按钮的方法永远不会被解雇。
我认为这种行为的原因是因为我的ListView的数据绑定仅在第一页加载时发生,而不是在每次后续回发时发生。因此,当发生回发时,嵌套网格视图的事件永远不会再次连线 - 因此我的方法不会被触发。
以下是我的代码[简化]的样子:
<asp:ListView ID="uiListView" ... runat="server">
<LayoutTemplate>
...
</LayoutTemplate>
<ItemTemplate>
...
<asp:GridView ID="uiGridView"
OnRowDataBound="uiGridView_RowDataBound"
OnRowEditing="uiGridView_RowEditing"
OnRowDeleting="uiGridView_RowDeleting" runat="server">
<Columns>
...
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="uiEditRowButton" CausesValidation="false" CommandName="Edit" Text="Edit" runat="server" />
<asp:Button ID="uiRemoveRowButton" CausesValidation="false" CommandName="Delete" Text="Remove" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
...
</ItemTemplate>
</asp:ListView>
代码背后:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack) {
uiListView.ItemDataBound += new EventHandler<ListViewItemEventArgs>(uiListView_ItemDataBound);
uiListView.DataSource = ...;
uiListView.DataBind();
}
}
// Find a GridView and bind relevant data to it
private void uiListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem) {
ListViewDataItem listViewDataItem = (ListViewDataItem) e.Item;
GridView uiGridView = (GridView)listViewDataItem.FindControl("uiGridView");
...
uiGridView.DataSource = ...;
uiGridView.DataBind();
}
}
// For every row being bound to GridView, register the edit and delete
// buttons as postback controls
protected void uiGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Control uiEditButton = e.Row.FindControl("uiEditRowButton");
if (uiEditButton != null) {
ScriptManager.GetCurrent(Page).RegisterAsyncPostBackControl(uiEditButton);
}
Control uiRemoveRowButton = e.Row.FindControl("uiRemoveRowButton");
if (uiRemoveRowButton != null) {
ScriptManager.GetCurrent(Page).RegisterAsyncPostBackControl(uiRemoveRowButton);
}
}
}
// Method runs when a GridView's edit button is clicked
protected void uiGridView_RowEditing(object sender, GridViewEditEventArgs e)
{
Console.WriteLine('Editing Row...');
}
// Method runs when a GridView's delete button is clicked
protected void uiGridView_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
Console.WriteLine('Deleting Row');
}
我尝试修改上面的代码并删除“!IsPostBack”子句,并且当单击GridView中的按钮时实际触发了事件。但是,我觉得在每个回发上做一个数据绑定并不舒服,并认为应该有一个更好的解决方案。
答案 0 :(得分:2)
我知道这篇文章已经过时了,但我很晚才开始研究我的项目。我不是专家,但我相信问题在于在Postback中设置ItemDataBound事件。 Databind()可以保留在Postback语句中,但设置事件需要在外部。在回发时,ItemDataBound事件不再存在,因此gridview事件不存在,因为它包含在listview的ItemDataBound事件中。所以
if (!IsPostBack) {
uiListView.ItemDataBound += new EventHandler<ListViewItemEventArgs>(uiListView_ItemDataBound);
uiListView.DataSource = ...;
uiListView.DataBind();
}
应该阅读......
uiListView.ItemDataBound += new EventHandler<ListViewItemEventArgs>(uiListView_ItemDataBound);
if (!IsPostBack) {
uiListView.DataSource = ...;
uiListView.DataBind();
}
在代码后面的控件上设置事件时,通常最好始终将它们设置在Posback语句之外。在aspx页面上设置它们无关紧要,因为它始终存在。
答案 1 :(得分:1)
我解决了这个问题,但从未更新过这篇文章。所以对于任何感兴趣的人来说,问题是什么 - 按钮事件的连接需要在 RowCreated 事件处理程序而不是RowCommand事件处理程序中完成。
为什么?看看MSDN对这两个事件中的每个事件都要说些什么:
GridView.OnRowCreated方法:
在 可以渲染GridView控件, 必须创建GridViewRow对象 对于控件中的每一行。该 每个都引发RowCreated事件 GridView控件中的行是 创建。这使您可以提供 执行的事件处理方法 自定义例程,例如添加 自定义内容到一行,无论何时 事件发生。
GridView.OnRowDataBound方法:
在可以渲染GridView控件之前, 必须绑定控件中的每一行 到数据源中的记录。该 一个时引发RowDataBound事件 数据行(由GridViewRow表示 对象)绑定到的数据 GridView控件。这使您能够 提供一种事件处理方法 执行自定义例程,例如 修改数据绑定的值 每当这个事件发生时 发生。
现在msdn写的不清楚如下:
当一个行由两个不同的源创建时触发OnRowCreated
因此,当发生回发时,我们需要在每一行上再次绑定按钮事件。但是,因为我们在RowCommand中进行事件连接,所以这些方法永远不会被再次调用 - 因为它们只会在DataBind上被触发。我们需要做的是将RowCreated方法中的按钮连接起来,当我们第一次将数据绑定到GridView时,以及从GridView的ViewState创建行时,每次回发都会调用这些按钮。