【问题标题】:Nested GridView not firing row events嵌套的 GridView 不触发行事件
【发布时间】:2010-08-04 10:52:29
【问题描述】:

我有一个嵌套在 ListView 中的 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 内的按钮时,事件实际上被触发了。但是,我对每次回发都进行数据绑定感到不舒服,我认为应该有比这更好的解决方案。

【问题讨论】:

    标签: c# asp.net gridview


    【解决方案1】:

    我知道这篇文章很旧,但很晚才发现我的项目。我不是专家,但我认为问题在于在 !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 页面上设置它们时,这无关紧要,因为它将始终存在。

    【讨论】:

      【解决方案2】:

      我解决了这个问题,但从未更新过这篇文章。所以对于任何感兴趣的人来说,这就是问题所在 - 按钮事件的连接需要在 RowCreated 事件处理程序而不是 RowCommand 事件处理程序中完成。

      这是为什么呢?看看 MSDN 对这两个事件中的每一个都说了些什么:

      GridView.OnRowCreated 方法:

      之前 可以呈现 GridView 控件, 必须创建一个 GridViewRow 对象 对于控件中的每一行。这 当每个 GridView 控件中的行是 创建的。这使您能够提供 执行的事件处理方法 自定义例程,例如添加 自定义内容到一行,每当这个 事件发生。

      GridView.OnRowDataBound 方法:

      在可以呈现 GridView 控件之前, 控件中的每一行都必须绑定 到数据源中的记录。这 RowDataBound 事件在发生时引发 数据行(由 GridViewRow 表示 对象)绑定到中的数据 GridView 控件。这使您能够 提供事件处理方法 执行自定义例程,例如 修改数据绑定的值 到行,每当这个事件 发生。

      现在从 msdn 的文章中不清楚的是:

      OnRowCreated 在由两个不同来源创建行时触发

      1. 从 DataSource - 在调用 DataBind 时传递
      2. 从 ViewState - 在回发时,行是从 ViewState 而不是从数据源加载的

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-26
        • 2017-06-11
        • 1970-01-01
        相关资源
        最近更新 更多