I need to sort my records by date (month & year) as displayed on my asp.net page;
Any ideas / suggestions would be helpful.
This is the code I currently ha
You can do this with a Repeater. Something like this (you should be able to adapt it easily):
<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>
On Code Behind, the OnItemDataBound
looks like this:
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
The way I bound my data to the repeater is like this:
Dim fi As FileInfo() = New DirectoryInfo("C:\").GetFiles().OrderByDescending(Function(x) x.CreationTime).ToArray()
rpt.DataSource = fi
rpt.DataBind()
Produces this output:
The ASP.NET content that you have should be put in a Repeater
. The files
that you have should then be grouped by the month and date. So basically you will end up with a parent-child list. The parent which is the group of files will be bound to the Repeater
, and the children which are the files belonging to that group will be bound the the GridView
in the Repeater
.
The ASP.NET content would be something along this line. Take note the gvInvoiceList
DataSource
property is bound to InvoiceList
, a property of the group that I came up with (which you will see in the code below) that will have a list of files belonging to the group.
<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>
As for the code, I'm not fluent on using DataTable
to have the parent-child relationship needed for the ASP.NET structure that I used for my answer, but it should be easily doable using normal classes. And I'm also not fluent on using VB.NET, so excuse my example which will be using C#, which I guess you should able to convert it quite easily to VB.NET.
I'm using Linq
to do the grouping and an anonymous class to have the parent-child relationship for this, so the code is rather short.
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: The code was written in a text editor and untested. Let me know if you face any errors. :)