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,…”
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"};
// populate the group list
foreach(string group in groupName)
listView1.Groups.Add(new ListViewGroup(group));
}
[more]
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)
{
// Because week starts on Monday in France
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; // same day
if (ts == 1)
return -1; // day before
if (ts == -1)
return 1; // day after
// same week
if ((ts > 1) && (ts <= dtRefWeekDay))
return dtWeekDay - 8;
if ((-ts > 1) && (-ts <= 6 - dtRefWeekDay))
return dtWeekDay + 2;
// previous / next weeks
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 for every item the Group property as follow:
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 ...
PS: as I am French, weeks start on monday, sorry ;)
PPS: you can download the whole solution here: