views:

39

answers:

0

I have a nested GridView that is placed inside a ListView. The GridView renders perfectly fine with all the entities that are bound inside its datasource.

Each record in my gridview has two buttons - 'delete' and 'edit'. The issue that I am having is that the methods wired to each of these buttons never get fired.

I think the reason for this behaviour is because my ListView's data binding happens only on the first page load, and not on every subsequent postback. As a result, when a postback happens, the events of the nested gridview are never wired up again - hence my methods are not getting fired.

Here is what my code [simplified] looks like:

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

Code Behind:

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');
}

I tried modifying the above code and removing the "!IsPostBack" clause, and the events actually got fired when a button inside the GridView was clicked. However, I do not feel comfortable doing a databind on every postback and think there should be a better solution than that.