【问题标题】:Displaying records grouped by month and year in asp.net在asp.net中显示按月和年分组的记录
【发布时间】:2011-10-11 11:17:12
【问题描述】:

我需要按照我的 asp.net 页面上显示的日期(月和年)对我的记录进行排序;
任何想法/建议都会有所帮助。

这是我目前拥有的代码

                <table width="40%" border="0" style="margin-left:auto; margin-right:auto;">
                    <tr><td><asp:Label ID="lblGridHeader" CssClass="TextFont" Text="" runat="server"></asp:Label></td></tr>
                    <tr>
                        <td align="center">
                            <asp:GridView ID="gvInvoiceList" runat="server" AutoGenerateColumns="false" AllowSorting="true">
                                <columns>
                                    <asp:TemplateField ItemStyle-Width="10%" HeaderText="File Type">
                                        <ItemTemplate><asp:HyperLink ID="imgFileType" ImageUrl="images/Icon_Pdf.gif" NavigateUrl='<%# SetNavigateUrl(Eval("Name")) %>' runat="server"></asp:HyperLink></ItemTemplate>
                                    </asp:TemplateField>
                                  <asp:boundfield datafield="Name" headertext="Invoice #"/>
                                  <asp:boundfield datafield="LastWriteTime" headertext="Date Modified"/>
                                </columns>
                            </asp:GridView>
                        </td>
                    </tr>
                </table>

背后的代码:

    If files.Count > 0 Then
        Dim DT As New DataTable()
        DT.Columns.Add(New DataColumn("Name", System.Type.GetType("System.String")))
        DT.Columns.Add(New DataColumn("LastWriteTime", System.Type.GetType("System.String")))

        Dim strCurrentMonth As String = ""

        For Each f As FileInfo In files
            If (MonthName(f.LastWriteTime.Month) <> strCurrentMonth) And (strCurrentMonth <> "") Then
                gvInvoiceList.DataSource = DT
                gvInvoiceList.DataBind()

                lblGridHeader.Text = MonthName(f.LastWriteTime.Month) & " - " & Year(f.LastWriteTime)
            Else
                lblGridHeader.Text = MonthName(f.LastWriteTime.Month) & " - " & Year(f.LastWriteTime)
            End If

            Dim Row1 As DataRow
            Row1 = DT.NewRow()
            Row1("Name") = f.Name
            Row1("LastWriteTime") = f.LastWriteTime
            DT.Rows.Add(Row1)

            strCurrentMonth = MonthName(f.LastWriteTime.Month)
        Next
        gvInvoiceList.DataSource = DT
        gvInvoiceList.DataBind()
    Else
        lblSummary.Text = "No data to show."
    End If  

【问题讨论】:

  • 包括有关记录如何分组的一些详细信息。在不知道数据是什么样子的情况下,很难将您的需求可视化。
  • 我不明白你为什么需要一个循环。如果数据库正在为您进行分组,您不能只显示查询结果吗?
  • 我需要将它们显示在单独的块中,标题为“月年”
  • 如果我是正确的,这可能需要客户端上的&lt;span&gt; 标记,然后动态创建gridview 的实例。

标签: asp.net vb.net gridview


【解决方案1】:

您可以使用中继器来做到这一点。 类似的东西(你应该能够轻松适应它):

<asp:Repeater ID="rpt" runat="server" OnItemDataBound="rpt_RowDataBound">
        <ItemTemplate>
            <table runat="server" style="color: White; background-color: #3A4F63;" visible="false"
                id="headerTable">
                <tr>
                    <td colspan="3">
                        <asp:Label ID="headerTitle" runat="server"></asp:Label>
                    </td>
                </tr>
                <tr>
                    <td style="width: 200px; background-color: #3A4F63; color: White;">
                        Name
                    </td>
                    <td style="width: 200px;">
                        Directory Name
                    </td>
                    <td style="width: 200px;">
                        Creation Time
                    </td>
                </tr>
            </table>
            <!-- These are the actual data items -->
            <!-- Bind to your specific properties i.e. Invoice #, file type, etc. -->
            <table>
                <tr>
                    <td style="width: 200px;">
                        <asp:Label ID="lblName" runat="server" Text='<%#Eval("Name") %>'></asp:Label>
                    </td>
                    <td style="width: 200px;">
                        <asp:Label ID="lblDirName" runat="server" Text='<%#Eval("DirectoryName") %>'></asp:Label>
                    </td>
                    <td style="width: 200px;">
                        <asp:Label ID="lblCreationTime" runat="server" Text='<%#Eval("CreationTime") %>'></asp:Label>
                    </td>
                </tr>
            </table>
        </ItemTemplate>
    </asp:Repeater>

在代码背后,OnItemDataBound 看起来像这样:

Private month As Integer = -1
Private year As Integer = -1
Protected Sub rpt_RowDataBound(sender As Object, e As RepeaterItemEventArgs)

    If e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = ListItemType.AlternatingItem Then
    'Binding to FileInfo objects. You are binding to DataTable. Adjust it accordingly
        If month <> TryCast(e.Item.DataItem, FileInfo).CreationTime.Month OrElse year <> TryCast(e.Item.DataItem, FileInfo).CreationTime.Year Then
            month = TryCast(e.Item.DataItem, FileInfo).CreationTime.Month
            year = TryCast(e.Item.DataItem, FileInfo).CreationTime.Year
            e.Item.FindControl("headerTable").Visible = True
            TryCast(e.Item.FindControl("headerTitle"), Label).Text = "Files for " & TryCast(e.Item.DataItem, FileInfo).CreationTime.ToShortDateString()
        Else
            e.Item.FindControl("headerTable").Visible = False
        End If
    End If
End Sub

我将数据绑定到中继器的方式是这样的:

Dim fi As FileInfo() = New DirectoryInfo("C:\").GetFiles().OrderByDescending(Function(x) x.CreationTime).ToArray()
rpt.DataSource = fi
rpt.DataBind()

产生这个输出:

【讨论】:

  • 非常感谢。不过,你在哪里按日期排序?
  • @DotNetRookie 是的,如果您希望能够正确构造标题,则需要这样做。如果您担心的话,在 DataTable 中执行此操作很简单。您可以简单地执行 dataTable.DefaultView.Sort 或使用 Linq(就像我一样)。
  • 不,你的方法行得通。我只需要对你得到的记录进行反向排序(并按月和年分组)......除此之外它效果很好
  • 没关系,我发现 (OrderByDescending) 更改为 OrderBy
  • @DotNetRookie 我做了OrderByDescending(Function(x) x.CreationTime).ToArray(),因为我认为首先显示最近的更有用;如果你需要逆向,只需使用OrderBy 而不是OrderByDescending。例如:OrderBy(Function(x) x.CreationTime).ToArray()。当然,如果您使用 Linq。如果你使用 dataTable.DefaultView.Sort 你可以做.Sort("CreationTime ASC");
【解决方案2】:

您拥有的 ASP.NET 内容应该放在Repeater 中。然后,您拥有的 files 应按月份和日期分组。所以基本上你最终会得到一个父子列表。作为文件组的父级将绑定到Repeater,属于该组的文件的子级将绑定到Repeater中的GridView


ASP.NET 内容

ASP.NET 内容将与此类似。请注意 gvInvoiceList DataSource 属性绑定到 InvoiceList,这是我提出的组的属性(您将在下面的代码中看到),它将包含属于该组的文件列表。

<asp:Repeater ID="repInvoiceGroups" runat="server">
    <ItemTemplate>
        <table width="40%" border="0" style="margin-left:auto; margin-right:auto;">
            <tr><td><asp:Label ID="lblGridHeader" CssClass="TextFont" 
                               Text='<%# Eval("MonthYear", "{0:MMMM yyyy}") %>' 
                               runat="server"></asp:Label></td></tr>
            <tr>
                <td align="center">
                    <asp:GridView ID="gvInvoiceList" runat="server" 
                                  AutoGenerateColumns="false" AllowSorting="true" 
                                  DataSource='<%# Eval("InvoiceList") %>'>
                        <columns>
                            <asp:TemplateField ItemStyle-Width="10%" HeaderText="File Type">
                                <ItemTemplate><asp:HyperLink ID="imgFileType" ImageUrl="images/Icon_Pdf.gif" NavigateUrl='<%# SetNavigateUrl(Eval("Name")) %>' runat="server"></asp:HyperLink></ItemTemplate>
                            </asp:TemplateField>
                          <asp:boundfield datafield="Name" headertext="Invoice #"/>
                          <asp:boundfield datafield="LastWriteTime" headertext="Date Modified"/>
                        </columns>
                    </asp:GridView>
                </td>
            </tr>
        </table>
    </ItemTemplate>
</asp:Repeater>


代码隐藏

至于代码,我不擅长使用DataTable 来获得我用于回答的 ASP.NET 结构所需的父子关系,但使用普通类应该很容易实现。而且我也不擅长使用 VB.NET,所以请原谅我的示例将使用 C#,我想您应该能够很容易地将其转换为 VB.NET。

我正在使用Linq 进行分组和一个匿名类来建立父子关系,所以代码比较短。

repInvoiceGroups.DataSource = files
    .GroupBy(f => f.LastWriteTime.ToString("yyyy-MM"))
    .Select(g => new { 
        MonthYear = DateTime.ParseExact(g.Key, "yyyy-MM", CultureInfo.InvariantCulture), 
        InvoiceList = g.OrderByDescending(f => f.LastWriteTime) })
    .OrderByDescending(o => o.MonthYear);
repInvoiceGroups.DataBind();


p/s:代码是在文本编辑器中编写的,未经测试。如果您遇到任何错误,请告诉我。 :)

【讨论】:

  • 这看起来不错,但它不会为每个文件组(月-年)生成他想要的标题。
  • @Icarus,是的,它会(至少它应该是,我没有测试它)。这就是Text='&lt;%# Eval("MonthYear", "{0:MMMM yyyy}") %&gt;' 的用途。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-27
  • 1970-01-01
  • 1970-01-01
  • 2013-03-30
  • 1970-01-01
  • 2011-03-22
  • 1970-01-01
相关资源
最近更新 更多