Home All Groups Group Topic Archive Search About
Author
8 Nov 2006 10:38 PM
Jakob Lithner
I have a usercontrol where I intend to list all responsibilities a person has
for the coming weeks. In the section I will write the day, date and month. In
the row I will write a description of the responsibility.

<asp:Repeater ID="repResponsibility" runat="server">
    <ItemTemplate>
        <div class="adSection"><asp:Literal id="litSection"
runat="server"></asp:Literal></div>
        <div class="adRow"><asp:Literal id="litRow"
runat="server"></asp:Literal></div>
    </ItemTemplate>
</asp:Repeater>

Section and Row are formatted with an appropriate CSS-class.
To the Repeater I connect a collection and pick the values:

    Protected Sub repResponsibility_ItemDataBound(ByVal sender As Object,
ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles
repResponsibility.ItemDataBound
        Dim r As Responsibility

        Dim litSection As Literal
        Dim litRow As Literal

        Select Case e.Item.ItemType
            Case ListItemType.Item
                r = CType(e.Item.DataItem, Responsibility)

                'Point out controls
                litSection = CType(e.Item.FindControl("litSection"), Literal)
                litRow = CType(e.Item.FindControl("litRow"), Literal)

                'Set values
                litSection.Text = r.ActivityStart.Value.ToString("dddd d
MMMM kl.HH")
                litRow.Text = String.Format("{0}, {1}", r.Person,
r.ResponsibilityTypeName)
        End Select
    End Sub


All works fine. But it would be much nicer if I could group all
responsibilities that belongs to the same date under ONE section heading.
Do I really need to have two collections and two nested repeaters to
accomplish this, or is there a better alternative?

Author
9 Nov 2006 11:29 AM
Walter Wang [MSFT]
Hi,

I'm not aware of any built-in controls can do that grouping for you, I'm
afraid you'll have to do that manually such as using nested repeaters. Let
me know if you need help on this.

By the way, you might also need to include ListItemType.AlternatingItem in
the Select Case check.

Sincerely,
Walter Wang (waw***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications. If you are using Outlook Express, please make sure you clear the
check box "Tools/Options/Read: Get 300 headers at a time" to see your reply
promptly.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
Author
9 Nov 2006 11:53 AM
Jakob Lithner
I see. Thanks for the advice.
Two nested repeaters and collections really seems like overkill .....
Maybe it is possible to check for repeated identical sections and in that
case hide them? I think I will have a try with that.
Author
10 Nov 2006 2:09 AM
Walter Wang [MSFT]
Hi,

That's a good idea to hide the sections after the data binding is
completed. You just need to enumerate the repeater item and check if the
section text is identical to previous one. Since Repeater doesn't have an
event called DataBound, I think this can be done right after you called
Repeater.DataBind().

Let me know if you need more info on this.

Regards,
Walter Wang (waw***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
Author
10 Nov 2006 12:46 PM
Jakob Lithner
I am not sure I got your idea, to do the hiding AFTER the data binding ....?

I find it more natural to keep doing it in the ItemDataBound event, where I
have all the information needed.

The biggest problem was to find a way to hide/collapse the section.
In my initial example I did the line breaks by using <DIV>-tags, but the
problem with them is that they will occupy space even when they have no
InnerHTML. And I was not able to get hold of them to change attributes from
code. Is it possible?

Next I tried TextBox control. It is easy to get hold of from code and I was
able to hide border and set ReadOnly. So I had clean VB-code, but I was not
able to get rid of all visual padding .... It kept looking strange, despite
my efforts.

So my final solution was to switch to Label-controls. Setting "display:
block" will give the Label a similar block behaviour as the previous
<DIV>-tag. By changing the CSS-style I was able to hide it from code
depending on data values.

I am not perfectly happy about dragging CSS-layout into the code, but it
works fine and looks nice!

Suggestion on improvements are welcome.



CSS-template
============================
..gadgetSection
{
    display: block;
    font-weight: bold;
    margin-top: 10px;
}
..gadgetLine

    display: block;
}



ASP-code
============================
<asp:Repeater ID="repLista" runat="server">
    <ItemTemplate>
         <asp:Label ID="lblSection" CssClass="gadgetSection"
runat="server"></asp:Label>
        <asp:Label ID="lblLine" CssClass="gadgetLine"
runat="server"></asp:Label>
    </ItemTemplate>
</asp:Repeater>





Code-behind
============================
    Protected Sub repLista_ItemDataBound(ByVal sender As Object, ByVal e As
System.Web.UI.WebControls.RepeaterItemEventArgs) Handles
repLista.ItemDataBound
        Dim lblSection As Label
        Dim lblLine As Label
        Dim dv As System.Data.DataRowView
        Dim c As dsNorthwind.CustomersRow
        Static lastCity As String = ""

        Select Case e.Item.ItemType
            Case ListItemType.Item, ListItemType.AlternatingItem

                'Grab the data
                dv = DirectCast(e.Item.DataItem, System.Data.DataRowView)
                c = CType(dv.Row, dsNorthwind.CustomersRow)

                'Find the controls
                lblSection = DirectCast(e.Item.FindControl("lblSection"),
Label)
                lblLine = DirectCast(e.Item.FindControl("lblLine"), Label)

                'Display data
                lblLine.Text = c.CompanyName
                If lastCity = c.City Then
                    lblSection.Style.Add("display", "none")
                Else
                    lblSection.Text = c.City
                End If

                'Remember value for comparison
                lastCity = c.City
        End Select
    End Sub
Author
13 Nov 2006 7:31 AM
Walter Wang [MSFT]
Hi,

Your solution is fine.

What I meant to do the grouping after the databinding is completed is
demonstrated using following code:

This is the business object:
====================

Public Class Responsibility
    Private m_activityStart As DateTime
    Public Property ActivityStart() As DateTime
        Get
            Return m_activityStart
        End Get
        Set(ByVal value As DateTime)
            m_activityStart = value
        End Set
    End Property
    Private m_person As String
    Public Property Person() As String
        Get
            Return m_person
        End Get
        Set(ByVal value As String)
            m_person = value
        End Set
    End Property
    Private m_responsibilityTypeName As String
    Public Property ResponsibilityTypeName() As String
        Get
            Return m_responsibilityTypeName
        End Get
        Set(ByVal value As String)
            m_responsibilityTypeName = value
        End Set
    End Property

    Public Sub New(ByVal activityStart As DateTime, ByVal person As String,
ByVal responsibilityTypeName As String)
        m_activityStart = activityStart
        m_person = person
        m_responsibilityTypeName = responsibilityTypeName
    End Sub

End Class


This is the web form:
================

    <form id="form1" runat="server">
        <div>
            <asp:Repeater ID="repResponsibility" runat="server">
                <ItemTemplate>
                    <div class="adSection">
                        <asp:Literal ID="litSection"
runat="server"></asp:Literal></div>
                    <div class="adRow">
                        <asp:Literal ID="litRow"
runat="server"></asp:Literal></div>
                </ItemTemplate>
            </asp:Repeater>
        </div>
    </form>


This is the code-behind of the web form:
===============================

    Protected Sub repResponsibility_ItemDataBound(ByVal sender As Object,
ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles
repResponsibility.ItemDataBound
        Dim r As Responsibility

        Dim litSection As Literal
        Dim litRow As Literal

        Select Case e.Item.ItemType
            Case ListItemType.Item, ListItemType.AlternatingItem
                r = CType(e.Item.DataItem, Responsibility)

                'Point out controls
                litSection = CType(e.Item.FindControl("litSection"),
Literal)
                litRow = CType(e.Item.FindControl("litRow"), Literal)

                'Set values
                litSection.Text = r.ActivityStart.ToString("dddd d MMMM")
                litRow.Text = String.Format("{0}, {1}", r.Person,
r.ResponsibilityTypeName)
        End Select
    End Sub

    Private Sub GroupBySections()
        Dim litSection As Literal
        Dim litRow As Literal

        Dim prevSection As String = String.Empty
        Dim currentSection As String

        For Each ri As RepeaterItem In Me.repResponsibility.Items
            If (ri.ItemType = ListItemType.AlternatingItem Or ri.ItemType =
ListItemType.Item) Then
                litSection = CType(ri.FindControl("litSection"), Literal)
                litRow = CType(ri.FindControl("litRow"), Literal)

                currentSection = litSection.Text
                If currentSection <> prevSection Then
                    prevSection = currentSection
                Else
                    litSection.Visible = False
                End If
            End If
        Next
    End Sub

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Me.Load
        Dim list As New List(Of Responsibility)
        Dim dt1 As DateTime = DateTime.Now
        list.Add(New Responsibility(dt1, "test1", "test"))
        list.Add(New Responsibility(dt1, "test2", "test"))
        Dim dt2 As DateTime = dt1.AddDays(1)
        list.Add(New Responsibility(dt2, "test3", "test"))
        list.Add(New Responsibility(dt2, "test4", "test"))
        Me.repResponsibility.DataSource = list
        Me.repResponsibility.DataBind()

        GroupBySections()
    End Sub



As you can see from above code, actually we only need to set the literal's
Visible property to False to exclude it from the output. You can verify
that the <div> of the hidden section doesn't exists in the html source.

Anyway, I believe this is only two different approach to the same objective.

Let me know if you need further information on this. Thanks.

Regards,
Walter Wang (waw***@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.