嵌套GridView不会触发行事件

时间:2010-08-04 10:52:30

标签: c# asp.net gridview

我有一个嵌套在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中的按钮时实际触发了事件。但是,我觉得在每个回发上做一个数据绑定并不舒服,并认为应该有一个更好的解决方案。

2 个答案:

答案 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

  1. 从DataSource - 调用DataBind时传递
  2. 从ViewState - 回发时,行从ViewState加载,而不是从数据源加载
  3. 因此,当发生回发时,我们需要在每一行上再次绑定按钮事件。但是,因为我们在RowCommand中进行事件连接,所以这些方法永远不会被再次调用 - 因为它们只会在DataBind上被触发。我们需要做的是将RowCreated方法中的按钮连接起来,当我们第一次将数据绑定到GridView时,以及从GridView的ViewState创建行时,每次回发都会调用这些按钮。

相关问题