ASP.Net ListView Grouping by Data Field?
Asked Answered
J

2

7

I uses asp.net listview control to display the details. Each item has the group details. For demo purposes group is hard coded.

I want to display the listview as shown below

enter image description here

Right now, I have this

enter image description here

Code:

    <asp:ListView ID="HyperLinkListView" runat="server" ViewStateMode="Disabled" ItemPlaceholderID="itemContainer" GroupPlaceholderID="groupContainer">
    <LayoutTemplate>
        <section class="quick-links">
            <div class="row">
                <div class="dfwp-column" style="width: 100%">
                    <div class="slm-layout-main groupmarker">
                        <ul class="dfwp-list">
                            <asp:PlaceHolder ID="groupContainer" runat="server" />
                        </ul>
                    </div>
                </div>
            </div>
        </section>
    </LayoutTemplate>
    <GroupTemplate>
        <span>Group</span>
        <asp:PlaceHolder ID="itemContainer" runat="server" />
    </GroupTemplate>
    <ItemTemplate>
        <li>
            <div class="item">
                <div class="link-item">
                    <asp:HyperLink Target="_blank" ID="hyperlink" NavigateUrl='<%# this.LinkToPlay((((SPListItem)Container.DataItem)["VideoFileName"]).ToString()) %>' Text='<%# Eval("Title") %>' runat="server" />
                    </a>
                </div>
            </div>
        </li>
    </ItemTemplate>
    <EmptyDataTemplate>
        <span>No data was returned.</span>
    </EmptyDataTemplate>
</asp:ListView>

How do I achieve this?

Julio answered 21/3, 2018 at 21:55 Comment(2)
Why you don't use asp:Repeater controls?Children
I used a repeater embedded within the ListView, using @Wael Abbas answer, I used the ItemDataBound event to pull a subset based on the group's e.item.dataitem value and bind the repeater.Esbensen
P
4

For a flexible solution, you can use nested ListView
enter image description here
You will need to update your HTML and CSS to get the desired appearance.

ASPX Code

<asp:ListView ID="GroupsListView" runat="server" ViewStateMode="Disabled" ItemPlaceholderID="groupContainer" OnItemDataBound="GroupsListView_ItemDataBound">
    <LayoutTemplate>
        <section class="quick-links">
            <div class="row">
                <div class="dfwp-column" style="width: 100%">
                    <div class="slm-layout-main groupmarker">
                        <asp:PlaceHolder ID="groupContainer" runat="server" />
                    </div>
                </div>
            </div>
        </section>
    </LayoutTemplate>
    <ItemTemplate>
        <ul class="dfwp-list">
            <li><%# Eval("Title") %></li>
            <div>
                <asp:ListView runat="server" ID="ItemsListView" ItemPlaceholderID="itemContainer">
                    <LayoutTemplate>
                        <section class="quick-links">
                            <div class="row">
                                <div class="dfwp-column" style="width: 100%">
                                    <div class="slm-layout-main groupmarker">
                                        <ul class="dfwp-list">
                                            <asp:PlaceHolder ID="itemContainer" runat="server" />
                                        </ul>
                                    </div>
                                </div>
                            </div>
                        </section>
                    </LayoutTemplate>
                    <ItemTemplate>
                        <li>
                            <div class="item">
                                <div class="link-item">
                                    <asp:HyperLink Target="_blank" ID="hyperlink" NavigateUrl='<%# Eval("Url") %>' Text='<%# Eval("Title") %>' runat="server" />
                                    </a>
                                </div>
                            </div>
                        </li>
                    </ItemTemplate>
                </asp:ListView>
            </div>
        </ul>
    </ItemTemplate>
    <EmptyDataTemplate>
        <span>No data was returned.</span>
    </EmptyDataTemplate>
</asp:ListView>

In the code behind you need to bind the child ListView in parent ItemDataBound event.

protected void GroupsListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{
    ListView itemsListView = (ListView)e.Item.FindControl("ItemsListView");
    if (e.Item.ItemType == ListViewItemType.DataItem)
    {

        itemsListView.DataSource = ((Group)e.Item.DataItem).Items;
        itemsListView.DataBind();
    }
}
Parr answered 30/3, 2018 at 18:5 Comment(2)
I'm having trouble finding the namespace for the type: (Group)Decompensation
My data source is an IEnumerable<IGrouping<string, MyClass)> so I replaced the line with the unknown (Group) cast to ((IGrouping<string, MyClass>)e.Item.DataItem).AsEnumerable() and it works great. ThanksCaprine
W
4

It is not quite clear what kind of grouping you want. However the ListView is limited in what it can do.

First of all you can only get a grouping by a fixed number of items. You can define that number with the GroupItemCount property. Your code would then look like this

<asp:ListView ID="HyperLinkListView" GroupItemCount="2" runat="server" ViewStateMode="Disabled" ItemPlaceholderID="itemContainer" GroupPlaceholderID="groupContainer">

And generate in html like this

GROUP
 My car video
 My sample video
GROUP
 Another sample video
 Item 4

Assuming you want GROUP A and GROUP B etc, you would normally use a binding expression, which looks like this

<GroupTemplate>
    <span>Group <%# Container.DataItemIndex %></span>
    <asp:PlaceHolder ID="itemContainer" runat="server" />
</GroupTemplate>

However the GroupItemTemplate is not part of the DataBind process, so getting and index based system will not work like that.

So a client side solution is needed if you want to add A, B etc. So first add a placeholder for the alhpa character and give the <span> a class so jQuery can find it. I've used {index} and groupIndex

<GroupTemplate>
    <span class="groupIndex">Group {index}</span>
    <asp:PlaceHolder ID="itemContainer" runat="server" />
</GroupTemplate>

Now with a simple jQuery method, all the placeholders are replaced with their correct alpha character.

<script type="text/javascript">
    $(document).ready(function () {
        $('.quick-links .groupIndex').each(function (index, element) {
            var char = String.fromCharCode(65 + index);
            $(this).html($(this).html().replace('{index}', char));
        });
    });
</script>

Note that the .quick-links comes from your <section class="quick-links"> part in the LayoutTemplate.

Whitney answered 24/3, 2018 at 21:18 Comment(2)
Thank you for the explanation. Group details are part of the item. Eg: "My car video;GroupA;car;Karthik;San Antonio"...so items should be grouped based on the column value in the Item itself. as well as GroupA may appear more than 2times while GroupB items be just be one.Julio
That seems rather random. You need a delimiter so identify the start of a new grouping. Like a "group" or "type" column. If you want it based on an arbitrary value in the Item, then it becomes nearly impossible to make a grouping because what will then be the trigger to start or end a grouping?Whitney
P
4

For a flexible solution, you can use nested ListView
enter image description here
You will need to update your HTML and CSS to get the desired appearance.

ASPX Code

<asp:ListView ID="GroupsListView" runat="server" ViewStateMode="Disabled" ItemPlaceholderID="groupContainer" OnItemDataBound="GroupsListView_ItemDataBound">
    <LayoutTemplate>
        <section class="quick-links">
            <div class="row">
                <div class="dfwp-column" style="width: 100%">
                    <div class="slm-layout-main groupmarker">
                        <asp:PlaceHolder ID="groupContainer" runat="server" />
                    </div>
                </div>
            </div>
        </section>
    </LayoutTemplate>
    <ItemTemplate>
        <ul class="dfwp-list">
            <li><%# Eval("Title") %></li>
            <div>
                <asp:ListView runat="server" ID="ItemsListView" ItemPlaceholderID="itemContainer">
                    <LayoutTemplate>
                        <section class="quick-links">
                            <div class="row">
                                <div class="dfwp-column" style="width: 100%">
                                    <div class="slm-layout-main groupmarker">
                                        <ul class="dfwp-list">
                                            <asp:PlaceHolder ID="itemContainer" runat="server" />
                                        </ul>
                                    </div>
                                </div>
                            </div>
                        </section>
                    </LayoutTemplate>
                    <ItemTemplate>
                        <li>
                            <div class="item">
                                <div class="link-item">
                                    <asp:HyperLink Target="_blank" ID="hyperlink" NavigateUrl='<%# Eval("Url") %>' Text='<%# Eval("Title") %>' runat="server" />
                                    </a>
                                </div>
                            </div>
                        </li>
                    </ItemTemplate>
                </asp:ListView>
            </div>
        </ul>
    </ItemTemplate>
    <EmptyDataTemplate>
        <span>No data was returned.</span>
    </EmptyDataTemplate>
</asp:ListView>

In the code behind you need to bind the child ListView in parent ItemDataBound event.

protected void GroupsListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{
    ListView itemsListView = (ListView)e.Item.FindControl("ItemsListView");
    if (e.Item.ItemType == ListViewItemType.DataItem)
    {

        itemsListView.DataSource = ((Group)e.Item.DataItem).Items;
        itemsListView.DataBind();
    }
}
Parr answered 30/3, 2018 at 18:5 Comment(2)
I'm having trouble finding the namespace for the type: (Group)Decompensation
My data source is an IEnumerable<IGrouping<string, MyClass)> so I replaced the line with the unknown (Group) cast to ((IGrouping<string, MyClass>)e.Item.DataItem).AsEnumerable() and it works great. ThanksCaprine

© 2022 - 2024 — McMap. All rights reserved.