LongListSelector日期分组列表

时间:2012-12-15 20:41:53

标签: xaml windows-phone-8 longlistselector

使用LongListSelector对日期进行分组的Windows Phone 8 SDK问题。 我熟悉grouping on letters的AlphaKeyGroup帮助方法。

是否有人为类似语言环境感知的日期做过/看过类似的写作? (数字也是一个加号)

4 个答案:

答案 0 :(得分:6)

所以我也对这个问题感到挣扎,因为你提到的MSDN中的AlphaKeyGroup示例因为本地化而比它需要的更复杂。您要做的是创建一个新的List对象,该对象具有一个额外的属性Key。此Key属性是您分组的名称。在AlphaKeyGroup示例中,它是您所在地区的每个字母。因此,创建自己的继承自List的组对象。

public class TimeKeyGroup<T> : List<T>
{
    /// <summary>
    /// The Key of this group.
    /// </summary>
    public string Key { get; private set; }

    public TimeKeyGroup(string key)
    {
        Key = key;
    }
}

现在创建一个名为CreateGroups的方法,该方法接受要分组的对象的IEnumerable,并返回刚刚创建的自定义列表对象的列表。在我的实现中,我正在对具有TimeStamp属性的Workout对象进行分组。在此方法中,为您想要的每种类型的组键名创建组对象,例如“过去7天”或“过去6个月”。然后通过浏览传入的IEnumerable组来填充每个组,并评估每个组以确定它们应该分组的位置。最后将每个分组列表添加到主组列表并返回它。这是我的方法:

public static List<TimeKeyGroup<Workout>> CreateGroups(IEnumerable<Workout> workouts)
    {
        // Create List to hold each item
        List<TimeKeyGroup<Workout>> groupedWorkouts = new List<TimeKeyGroup<Workout>>();

        // Create a TimeKeyGroup for each group I want
        TimeKeyGroup<Workout> LastSeven = new TimeKeyGroup<Workout>("Last Seven Days");
        TimeKeyGroup<Workout> LastTwoWeeks = new TimeKeyGroup<Workout>("Last Two Weeks");
        TimeKeyGroup<Workout> LastMonth = new TimeKeyGroup<Workout>("Last Month");
        TimeKeyGroup<Workout> LastSixMonths = new TimeKeyGroup<Workout>("Last Six Months");
        TimeKeyGroup<Workout> LastYear = new TimeKeyGroup<Workout>("Last Year");
        TimeKeyGroup<Workout> AllTime = new TimeKeyGroup<Workout>("All Time");

        // Fill each list with the appropriate workouts
        foreach (Workout w in workouts)
        {
            if (w.TimeStamp > DateTime.Now.AddDays(-7))
            {
                LastSeven.Add(w);
                continue;
            }
            else if (w.TimeStamp > DateTime.Now.AddDays(-14))
            {
                LastTwoWeeks.Add(w);
                continue;
            }
            else if (w.TimeStamp > DateTime.Now.AddMonths(-1))
            {
                LastMonth.Add(w);
                continue;
            }
            else if (w.TimeStamp > DateTime.Now.AddMonths(-6))
            {
                LastSixMonths.Add(w);
                continue;
            }
            else if (w.TimeStamp > DateTime.Now.AddMonths(-12))
            {
                LastYear.Add(w);
                continue;
            }
            else
            {
                AllTime.Add(w);
            }
        }

        // Add each TimeKeyGroup to the overall list
        groupedWorkouts.Add(LastSeven);
        groupedWorkouts.Add(LastTwoWeeks);
        groupedWorkouts.Add(LastMonth);
        groupedWorkouts.Add(LastSixMonths);
        groupedWorkouts.Add(LastYear);
        groupedWorkouts.Add(AllTime);

        return groupedWorkouts;
    }

现在你有一个很好的分组列表列表。真棒!其余的只是将LongListSelector的itemssource属性挂钩到这个新列表并定义JumpListStyle和GroupedHeaderTemplate。您引用的原始文章包含所有信息。

祝你好运,开心Windows Phone!

答案 1 :(得分:2)

在我和你现在被困在同一个例子后,我在this example from MSDN取得了成功。 Group.cs文件包含一个可以随字符串自由使用的组的实现。我的猜测是,您可以轻松添加DateTime的另一个属性,然后您可以尝试按日期分组。

答案 2 :(得分:1)

我使用AlphaKeyGroup的修改版本。这个新类我调用了StringKeyGroup,并根据项的第一个charachter创建组。所以这只是用StringKeyGroup替换AlphaKeyGroup的问题。

这个新功能可以像:

一样使用
myLonglistSelector.ItemSource = GroupedItems(myCollection);
....

public ObservableCollection<StringKeyGroup<myClass>> GroupedItems(IEnumerable<myClass> source)
    {
        return StringKeyGroup<myClass>.CreateGroups(source,
            System.Threading.Thread.CurrentThread.CurrentUICulture, 
            s => s.Name, true);
    }

这是StringKeyGroup.cs的代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using System.Globalization;

namespace MyNameSpace

{
public class StringKeyGroup<T> : ObservableCollection<T>
{
    public delegate string GetKeyDelegate(T item);
    public string Key { get; private set; }
    public StringKeyGroup(string key)
    {
        Key = key;
    }
    public static ObservableCollection<StringKeyGroup<T>> CreateGroups(IEnumerable<T> items, CultureInfo ci, GetKeyDelegate getKey, bool sort)
    {
        var list = new ObservableCollection<StringKeyGroup<T>>();

        foreach (var item in items)
        {
            var itemKey = getKey(item).Substring(0, 1).ToLower();

            var itemGroup = list.FirstOrDefault(li => li.Key == itemKey);
            var itemGroupIndex = itemGroup != null ? list.IndexOf(itemGroup) : -1 ;

            if (itemGroupIndex == -1)
            {
                list.Add(new StringKeyGroup<T>(itemKey));
                itemGroupIndex = list.Count - 1;
            }
            if (itemGroupIndex >= 0 && itemGroupIndex < list.Count)
            {
                list[itemGroupIndex].Add(item);
            }
        }

        if (sort)
        {
            foreach (var group in list)
            {
                group.ToList().Sort((c0, c1) => ci.CompareInfo.Compare(getKey(c0), getKey(c1)));
            }
        }

        return list;
    }
}
}  

答案 3 :(得分:0)

要将LongListSelector与数字一起使用,我们可以尝试按年龄对人员列表进行分组,而不是按名字的第一个字母(in the MSDN PeopleHub example

进行分组

他们使用神秘的AlphaKeyGroup,它是一个名字以相同字母开头的人的列表(该字母成为AlphaKeyGroup的Key)。 AlphaKeyGroups的人看起来像这样:

  • Key = A:Amber,Amelia(其中两个People对象的名称都以A开头)
  • Key = B:Bob,Brian(其中两个People对象的名称都以B开头)
  • Key = C:etc etc

我们将使用IntegerKeyGroup,它是具有相同年龄的人员列表。 IntegerKeyGroups的人看起来像这样:

  • Key = 23:Jennifer,Ryan(两个人物都是23岁)
  • Key = 26:Amber,Megan(两个People对象都是26岁)
  • Key = 34:etc etc

因此,要遵循GentryRiggen的框架,我们必须首先定义IntegerKeyGroup,然后将人们粘贴在他们所属的年龄组中。我把它们放在ViewModel文件中。

public class IntegerKeyGroup<T> : List<T>
{
    public int Key { get; private set; }

    public IntegerKeyGroup(int key)
    {
        Key = key;
    }
}

注意IntegerKeyGroup只是一个List,但有一个名为Key的特殊整数成员。这意味着我们可以将年龄整数的人员列表标记为密钥

现在我们需要将未分类的人员列表排序到不同年龄的IntegerKeyGroups中,最后将所有这些IntegerKeyGroups组合在一起。这个 IntegerKeyGroups的组合列表是LongListSelector接受显示的内容

public static List<IntegerKeyGroup<Person>> CreateGroups(IEnumerable<Person> UnsortedPeopleList)
{
    // Create combined list of IntegerKeyGroups
    List<IntegerKeyGroup<Person>> CombinedPeopleList = new List<IntegerKeyGroup<Person>>();

    // Create a IntegerKeyGroup for each age group I want,
    // The constructor parameters sets the Key to the IntegerKeyGroup
    IntegerKeyGroup<Person> Age23s = new IntegerKeyGroup<Person>(23);
    IntegerKeyGroup<Person> Age26s = new IntegerKeyGroup<Person>(26);
    IntegerKeyGroup<Person> Age34s = new IntegerKeyGroup<Person>(34);

    // Populate each IntegerKeyGroup with the appropriate Persons
    foreach (Person p in UnsortedPeopleList)
    {
        switch (p.Age)
        {
            case 23: Age23s.Add(p); continue;
            case 26: Age26s.Add(p); continue;
            case 34: Age34s.Add(p); continue;
            default: continue; // we don't support ages other than the 3 above 
        }
    }

    // Add each IntegerKeyGroup to the overall list
    CombinedPeopleList.Add(Age23s);
    CombinedPeopleList.Add(Age26s);
    CombinedPeopleList.Add(Age34s);

    return CombinedPeopleList;
}

仍然在ViewModel文件中,使用CreateGroups函数公开访问IntegerKeyGroups列表。

 public List<IntegerKeyGroup<Person>> AgeGroupedPeople
    {
        get
        {
            return CreateGroups(UnsortedPeople);
        }
    }

现在在XAML中,对MSDN PeopleHub example

中的原始代码进行1次更改
<phone:LongListSelector Name="peopleLongListSelector"   
     ItemsSource="{Binding AgeGroupedPeople}" <!-- Change is in this line! -->
     JumpListStyle="{StaticResource LongListSelectorJumpListStyle}"  
     ListHeaderTemplate="{StaticResource LongListSelectorHeaderTemplate}"
     GroupHeaderTemplate="{StaticResource LongListSelectorGroupHeaderTemmplate}"
     ItemTemplate="{StaticResource LongListSelectorItemTemplate}"
     HideEmptyGroups ="true" IsGroupingEnabled ="true" LayoutMode="List">
 </phone:LongListSelector>

这应该按整数分组,在这种情况下,年龄。