Introduction
Recently, I had to sort items in my listview. OK, I heard you, "nothing difficult doing that". But, I also had to group them as Outlook does. I mean "according to the date, today items, yesterday items, tomorrow items, next month items,...".
Using the Code
First of all, we have to define the label for each group:
private void Form1_Load(object sender, EventArgs e)
{
string[] groupName = {"Older",
"Last month", "4 weeks ago", "3 weeks ago",
"2 weeks ago", "Last week",
"Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday", "Sunday",
"Yesterday",
"Today",
"Tomorrow",
"Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday", "Sunday",
"Next week", "In 2 weeks",
"In 3 weeks", "In 4 weeks", "Next month",
"Newer"};
foreach(string group in groupName)
listView1.Groups.Add(new ListViewGroup(group));
}
Then, we have to define what group an item belongs to according to the current date and the item's date.
internal static int GetDateTimeGroupIndex(DateTime dtRef, DateTime dtSource)
{
int dtWeekDay = (Convert.ToInt32(dtSource.DayOfWeek) + 6) % 7;
int dtRefWeekDay = (Convert.ToInt32(dtRef.DayOfWeek) + 6) % 7;
int ts = (dtRef.Date - dtSource.Date).Days;
if (ts == 0)
return 0;
if (ts == 1)
return -1;
if (ts == -1)
return 1;
if ((ts > 1) && (ts <= dtRefWeekDay))
return dtWeekDay - 8;
if ((-ts > 1) && (-ts <= 6 - dtRefWeekDay))
return dtWeekDay + 2;
for (int nIdx = 0; nIdx <= 3; nIdx++)
{
if ((ts > dtRefWeekDay + nIdx * 7) &&
(ts <= dtRefWeekDay + (nIdx + 1) * 7))
if (dtRef.Month == dtSource.Month)
return -(9 + nIdx);
else
return -13;
if ((-ts > 6 - dtRefWeekDay + nIdx * 7) &&
(-ts <= 6 - dtRefWeekDay + (nIdx + 1) * 7))
if (dtRef.Month == dtSource.Month)
return (9 + nIdx);
else
return 13;
}
if (Math.Abs(dtSource.Month - dtRef.Month) == 1)
return Math.Sign(ts) * (-13);
return Math.Sign(ts) * (-14);
}
Finally, we have to set the Group
property for every item as follows:
DateTime dtDate = DateTime.Now.AddMonths(-2);
while(dtDate < DateTime.Now.AddMonths(2))
{
ListViewItem item = new ListViewItem("Item " +
dtDate.Date.ToString("dd/MM/yyyy"));
item.Group = listView1.Groups[GetDateTimeGroupIndex(DateTime.Now, dtDate) + 14];
listView1.Items.Add(item);
dtDate = dtDate.AddDays(1);
}
And the result is ...
Points of Interest
The thing to note is that groups are displayed in the same order they are created; that is why I create them from older to newer and why I repeat the day name: the first time for when the item is older than today (if it is Friday, items from last Wednesday will belong to the group labeled "Wednesday" - the first one, and if it is Monday, items from next Wednesday will belong to the group labeled "Wednesday" too, but the second one).
Then, when the listview is sorted, groups are sorted, and in each group, items are sorted too.
History
- 04/14/2009: First submission.