0

I have a nested GridView as follows:

<asp:GridView ID="gvParent" runat="server" DataKeyNames="id">
    <Columns>
        <asp:TemplateField>
            <ItemTemplate>
                <asp:GridView ID="gvChild" runat="server">
                    <Columns>
                        <asp:TemplateField>
                            <ItemTemplate>
                                <asp:Label ID="lblChild1" runat="server"/>
                            </ItemTemplate>
                        </asp:TemplateField>
                        //... some more child columns
                    </Columns>
                </asp:GridView>
            </ItemTemplate>
        </asp:TemplateField>

        <asp:TemplateField>
            <ItemTemplate>
                <asp:Label ID="lblParent1" runat="server"/>
            </ItemTemplate>
        </asp:TemplateField>
        //... some more parent columns
        <asp:TemplateField>
            <ItemTemplate>
                <asp:HiddenField ID="IsExpanded" ClientIDMode="Static" runat="server" />
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

What I want to do is when the user clicks anywhere on the parent row, the child row expands, showing all rows in the child GridView that relate to the parent then when I click again, it should collapse.

I can get the data into the GridViews fine and can get the expand/collapse working as in this tutorial but I don't want to have just the image clickable, I want the whole row clickable.

To at least try and get it to expand I used the same logic from the tutorial:

$(function () {
    $("[id*=gvParent] td").click(function () {
        $(this).closest("tr").after("<tr><td></td><td colspan = '999'>" + $(this).next().html() + "</td></tr>");
    });
});

But it just copies the contents of the column to the right of the clicked column within that row to the next row (see snip). I'm sure it's probably simple but I just can't find the answer anywhere!

UPDATE:

I now have:

$("[id*=gvFileUploadAdmin] td").click(function () {
    if ($("#IsExpanded").val() == "expanded") {
        debugger;
        collapseRow(this);
    }
    else if (typeof $("#IsExpanded").val() == 'undefined' 
            || $("#IsExpanded").val() == "collapsed") {
        expandRow(this);
    }
});

function expandRow(row) {
    $(row)
        .closest("tr")
        .after("<tr><td></td><td colspan = '999'>" +
            $("[id*=pnlFiles]", $(row).closest("tr")).html() +
            "</td></tr>");       
    $("#IsExpanded").val("expanded");
};

function collapseRow(row) {
    $(row).closest("tr").next().remove();
    $("#IsExpanded").val("collapsed");
}

Which allows me to open and close individual rows BUT when one row is open and then another is opened, the row beside that is deleted. There is definitely something going on with the unique IDs but I'm not sure how to fix it. I do have some C# in the background doing this:

HiddenField IsExpanded = row.FindControl("IsExpanded") as HiddenField;
var uniqueId = IsExpanded.UniqueID;
IsExpanded.Value = Request.Form[uniqueId];

But when that's removed it makes no difference to how it works because Request.Form[uniqueId] returns null.

madster
  • 23
  • 2
  • 6

2 Answers2

0

Have you tried using a Listview instead of a Gridview? I use a LinkButton to activate/deactivate the row expansion.

  1. In the ItemTemplate you enclose your display cells within the LinkButton definition.

<ItemTemplate>
  <tr>
    <td>
      <asp:LinkButton ID="LinkButton1" runat="server" CommandName="Select">
       LOC:
        <asp:Label Text='<%# Eval("LocationCode") %>' runat="server" ID="LocationCodeLabel" /></span>
      </asp:LinkButton>
    </td>
    <td>
      <asp:Button ID="editLocation" runat="server" Text="EDIT" CommandName="Edit" CommandArgument='<%# Eval("LocationID") %>' />
      <asp:Button ID="deleteLocation" runat="server" Text="DELETE" CommandName="Delete" CommandArgument='<%# Eval("LocationID") %>' />
    </td>
  </tr>
</ItemTemplate>
  1. Give the ItemTemplate's LinkButton CommandName="Select" - this has the effect of activating the SelectedItemTemplate.

  2. In the SelectedItemTemplate, surround the data cells with another LinkButton. The LinkButton CommandName="UnSelect".

The ListView handles the Select command for free. The UnSelect has to be handled by Listview1_ItemCommand() event handler.

protected void LocationView_ItemCommand(object sender, ListViewCommandEventArgs e)
{
    if (e.CommandName == "UnSelect")
    {
        ListView1.SelectedIndex = -1;
        ListView1.DataBind();
    }
}

You may insert your GridView into a Div in the SelectedItemTemplate. However another ListView Embedded in the SelectedItemTemplate would be ideal.

madster
  • 23
  • 2
  • 6
Renshai
  • 89
  • 1
  • 6
  • Thanks for your reply but according to [this question](http://stackoverflow.com/questions/891918/asp-net-grid-view-vs-list-view), a ListView isn't really what I'm looking for. Plus I want the whole row clickable, not just a button. – madster Jul 13 '16 at 15:52
  • The link button is invisible - it essentially makes the entire row Clickable/Selectable. – Renshai Jul 13 '16 at 17:03
  • Aoplogies for the oversight before. I have now implemented all of the above but the nested gridview does not show when the row is selected, the same list is shown. Then once it is selected again, all rows disappear. I don't think this is the correct approach anyway as I'm just repeating the fields in the selected item template plus I'll need to manually manipulate it to show in a grid format, whereas that is already there with a gridview. – madster Jul 14 '16 at 10:55
  • I get your frustration. I've been there. If rows are disappearing - it means that maybe the select event is not being fired - or you're not calling DataBind() after the postback operation. Maybe you have an updatepanel on the page. I am using .Net 4.5 Model binding techniques for instance (http://www.asp.net/web-forms/overview/presenting-and-managing-data/model-binding/updating-deleting-and-creating-data.) that ensures that pa – Renshai Jul 15 '16 at 17:20
0

So I finally managed to get it working! Here's what I did (note that this doesn't expand the row if the user presses a button within that row):

$(function () {
    $("[id*=gvParent] td").click(function () {
        if ($(this).parents('tr').find('input[type="hidden"]').val() == "expanded")
            collapseRow(this);
        else
            expandRow(this);
     });

     // Ensure the row doesn't expand/collapse if a button is clicked
     $("[id*=gvParent] td .btn").click(function (e) {
         e.stopPropagation();
     });
     //Ensures any clicks on the child row aren't registered
     $("[id*=gvParent] td .gvChild").click(function (e) {
         e.stopPropagation();
     });
});

function expandRow(row) {
    $(row).closest("tr").after("<tr><td></td><td colspan = '999'>" +
                $("[id*=pnlFiles]", $(row).closest("tr")).html() +
                "</td></tr>");
    $(row).parents('tr').find('input[type="hidden"]').val("expanded");
};

function collapseRow(row) {
    $(row).closest("tr").next().hide();
    $(row).parents('tr').find('input[type="hidden"]').val("collapsed");
}

I also changed the ClientIDMode from static:

<asp:HiddenField ID="IsExpanded" ClientIDMode="Static" runat="server" />

to AutoID:

<asp:HiddenField ID="IsExpanded" ClientIDMode="AutoID" runat="server" />
madster
  • 23
  • 2
  • 6