Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Grouping Infomation: The best ASP.NET control for the job

Status
Not open for further replies.

NuJoizey

MIS
Aug 16, 2006
450
US
I need a display control that groups information by business line, then by date and then by product name like so:
Code:
+ LINE-A
    + MOST RECENT EFFECTIVE DATE 
         ID#     PRODUCT   STATUS
         xx      xxxxx     xxxx
         yy      yyyyy     yyyy
    + NEXT MOST RECENT EFFECTIVE DATE 
         ID#     PRODUCT   STATUS
         aa      aaaaa     aaaa
         bb      bbbbb     bbbb
+ LINE-B
    + MOST RECENT EFFECTIVE DATE 
         ID#     PRODUCT   STATUS
         xx      xxxxx     xxxx
         yy      yyyyy     yyyy
    + NEXT MOST RECENT EFFECTIVE DATE 
         ID#     PRODUCT   STATUS
         aa      aaaaa     aaaa
         bb      bbbbb     bbbb
+ LINE-C
    + MOST RECENT EFFECTIVE DATE 
         ID#     PRODUCT   STATUS
         xx      xxxxx     xxxx
         yy      yyyyy     yyyy

Where I have indicated a + sign, i would like the child data to be collapsible, and of course if there's no data for LINE-C, then I'd like for LINE-C not to show up in my control.

I don't think a report will do, (but not being a report pro, i'm not sure) because I need interactivity on this display control, users will need to click on it to go to other places in my app. So I had considered possibly doing something with one of the AJAX accordion control (
But being rather new to the asp.net world, I am just not sure what's the best way to go with this - maybe there is something already out there that does this? If there is I haven't seen THE one yet. Possibly I might need to create a custom control that mixes and matches other controls out there, but I'm just not sure. So before I waste a lot of time with trial and error, I humbly request the opinion of you pros that hang out on this board.
 
if you build this by hand nested Repeater controls would be the way to go. Accordion control is not what your looking for. Only 1 panel of an accordion is visible at a time.

you will need to build the js to hide/show and retrieve (if ajax driven) the details within each group. hide/show wouldn't be an issue. that can be divs or tables. fetching/displaying data would require a webservice and some form of an ajax framework.



Jason Meckley
Programmer
Specialty Bakers, Inc.
 
i see how the treeview would deliver the hide/show, but can it do the group-by's and record rendering?
 
not sure what you mean by record rendering

You can display anything you want in a node of the tree view. What you would have to do(as I have done in the past) is to use a string builder and create the text you want to display in the node.

As for grouping, you have to do that with your sql, and build the tree as you need. There are many examples on line.
 
ok, so are you saying that I should be able to create the underlying data in my SQL (ungrouped), let's say in a view or something (which should be relatively simple to derive), and then use the treeview to display it in the way I have indicated? Since it's under the navigation heading in VS, I thought the treeview was for menus. I hadn't thought to use it for a data display.
 
You'll get more control over the final output if you use a Repeater. Treeviews can be for very useful displaying hierarchical information (which is essentially what you want) but they can output some horrible HTML unless used with a control adaptor.

Personally, I'd go with the repeater but this would involve you writing the extra javascript step to show/hide the collapsible regions.


-------------------------------------------------------

Mark,
[URL unfurl="true"]http://aspnetlibrary.com[/url]
[URL unfurl="true"]http://mdssolutions.co.uk[/url] - Delivering professional ASP.NET solutions
[URL unfurl="true"]http://weblogs.asp.net/marksmith[/url]
 
1st i would build the model in a pure postback scenario

1. on page load bind line-[A] list to a repeater.
2. in the item repeater add a link button with a command name like QueryEffectiveDate and a command argument for the id of Line[A]
3. define the itemcommandevent for the repeater. if the command name matches get the effective dates for line[a] and bind to a repeater nested within the same item as the link button.
4. repeate steps 2 and 3 for the details section.

in the end you would have 3 nested repeaters. the top 2 would have like buttons with command names/args to query the child data.

then wrap the nested repeaters with update panels that have conditional triggers to their specific link button. it's not a pure ajax solution but it uses the advantages of web forms events/databinding while elminiating the appearence of a full postback.

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
They I have done it with the treeview is to grab all the data at once(if it is not a lot), I also turn off viewstate for the treeview. This way, once the tree is built, there is no need for any postbacks.
 
what about somehow leveraging the the <ul> html element with the repeater, and then using javascript to somehow toggle the display of the sub elements?
 
I like jmeckley's solution for getting the data and displaying it, but you don't have to use Update Panels at all to hide/show. Instead, display a graphic for the '+' sign and then add some CSS to it... display:block or display:none ..... you don't have to mess with the partial postbacks of the AJAX Asp.Net controls this way.
 
tperri, the update panels would be used to dynamically load data, instead of loading it all up front. js would still be required to show hide detail.

if all the data was loaded at once then you are correct; no update panels would be required.

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
attempting to applying the jmeckley concepts to code, here is what I have so far. However I am stuck on trying to get the third level of the nested repeater to work. The first two seem to function as intended. The problem I am having seems to be that I cannot find a way to access "repeater2_ItemDatabound", or for that matter any property, method, event or control located within that repeater. Anything below repeater1 level seems "buried" and I have no idea how to expose it. Can you help me?

here is my aspx:
Code:
<asp:Content ID="contPlacementList" runat="server" ContentPlaceHolderID="cphMainContent">
    <div>
        <asp:Repeater ID="Repeater1" runat="server">
            <ItemTemplate>
                <div><asp:Label ID="lblLines" style="font-weight:bolder;" runat="server" Text='<%# Eval("Lines") %>'/></div>
                    <asp:Repeater ID="Repeater2" runat="server">
                        <ItemTemplate>
                            <div><asp:Label ID="lblTerm" runat="server" Text='<%# Eval("Term") %>'/></div>                        
                                <asp:Repeater ID="Repeater3" runat="server">
                                    <ItemTemplate>
                                        <asp:Label ID="lblThirdLevelData" runat="server" Text="Label"></asp:Label>
                                    </ItemTemplate> 
                                </asp:Repeater>
                        </ItemTemplate> 
                    </asp:Repeater>                
            </ItemTemplate>
        </asp:Repeater>
    </div>
</asp:Content>

Here is my VB:
Code:
 Imports System.Data
Imports System.Data.SqlClient
Partial Class placementList
    Inherits System.Web.UI.Page
    Private connstr As String = ConfigurationManager.ConnectionStrings("MyDatabaseConnectionString").ConnectionString

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Call BindOuterRepeater()
    End Sub


    Private Sub BindOuterRepeater()
        Dim cn As New SqlConnection(connstr)
        Dim da As New SqlDataAdapter("SELECT DISTINCT Lines FROM viewPlacementList ORDER BY Lines DESC", cn)
        Dim dt As New DataTable
        da.Fill(dt)
        cn.Close()
        Repeater1.DataSource = dt
        Repeater1.DataBind()
    End Sub

    Protected Sub Repeater1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles Repeater1.ItemDataBound
 
        Dim repRepeater2 As Repeater = CType(e.Item.FindControl("Repeater2"), Repeater)  
        Dim keyval As String = CType(e.Item.FindControl("lblLines"), Label).Text
        Call BindInnerRepeater(repRepeater2, keyval)

    End Sub

    Private Sub BindInnerRepeater(ByVal rep As Repeater, ByVal keyval As String)
        Dim sql As String = "SELECT DISTINCT Term FROM viewPlacementList WHERE Lines='" & keyval & "' ORDER BY Term DESC"
        Dim cn As New SqlConnection(connstr)
        Dim da As New SqlDataAdapter(sql, cn)
        Dim dt As New DataTable
        da.Fill(dt)
        cn.Close()

        rep.DataSource = dt
        rep.DataBind()
    End Sub
 
Code:
<asp:Repeater ID="Grouping1" runat="server">
    <ItemTemplate>
        <asp:LinkButton ID="Grouping1Link" runat="Server" CommandArgument='<%#Eval("IdOfGrouping1") %>' CommandName="GetGrouping2" OnCommand="ButtonCommands" />
        <asp:Repeater ID="Grouping2" runat="Server">
            <ItemTemplate>
                group 2 text goes here
                <asp:LinkButton ID="Grouping2Link" runat="Server" CommandArgument='<%#Eval("IdOfGrouping2") %>' CommandName="GetDetails" OnCommand="ButtonCommands" />
                <asp:Repeater ID="Details" runat="server">
                    <ItemTemplate>
                        details go here
                    </ItemTemplate>
                </asp:Repeater>
            </ItemTemplate>
        </asp:Repeater>
    </ItemTemplate>
</asp:Repeater>
Code:
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class _Default : Page
{
    protected override void OnLoad(System.EventArgs e)
    {
        base.OnLoad(e);
        if(!IsPostBack)
        {
            Grouping1.DataSource = GetGroup1Data();
        }
    }

    protected void ButtonCommands(object sender, CommandEventArgs e)
    {
        Repeater repeater;
        switch (e.CommandName)
        {
            case "GetGrouping2":
                repeater = (Repeater)((Control)sender).Parent.FindControl("Grouping2");
                repeater.DataSource = GetGroup2DataUsing(e.CommandArgument);
                repeater.DataBind();
                break;
            case "GetDetails":
                repeater = (Repeater)((Control)sender).Parent.FindControl("Details");
                repeater.DataSource = GetDetailsDataUsing(e.CommandArgument);
                repeater.DataBind();
                break;
        }
    }
}
here is one option. I'm not crazy about these lines
[tt](Repeater)((Control)sender).Parent.FindControl("?")[/tt]
but it's a start. this would assume you are loading data by section.

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top