Списки LongListSelector, сгруппированные по дате

Вопрос по Windows Phone 8 SDK с использованием LongListSelector для группировки по датам. Я знаком с вспомогательным подходом AlphaKeyGroup к группировка по буквам.

Кто-нибудь делал/видел подобную запись для дат, которые так же осведомлены о локали? (Цифры тоже будут плюсом)


person user1906865    schedule 15.12.2012    source источник


Ответы (4)


Так что я тоже немного боролся с этим, потому что пример AlphaKeyGroup из MSDN, который вы упомянули, более сложен, чем должен быть, из-за локализации. То, что вы пытаетесь сделать, это создать новый объект 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 объекта, который вы хотите сгруппировать, и возвращает список только что созданного вами пользовательского объекта списка. В моей реализации я группировал объекты Workout со свойством TimeStamp. В этом методе создайте групповые объекты для каждого типа имени ключа группы, которое вы хотите, например «Последние 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;
    }

Теперь у вас есть хороший список сгруппированных списков. Потрясающий! Остальное просто привязывает свойство itemssource вашего LongListSelector к этому новому списку и определяет JumpListStyle и GroupedHeaderTemplate. В исходной статье, на которую вы ссылаетесь, есть вся эта информация.

Удачи и счастливого развития Windows Phone!

person GentryRiggen    schedule 21.07.2013

Я успешно использовал этот пример из MSDN после Я застрял на том же примере, что и вы сейчас. Файл Group.cs содержит реализацию группы, которую можно свободно использовать со строками. Я предполагаю, что вы можете легко добавить еще одно свойство DateTime, а затем попробовать группировать по датам.

person Markus Rudel    schedule 17.12.2012

Ну, я использую модифицированную версию AlphaKeyGroup. Этот новый класс я назвал StringKeyGroup и создает группы на основе первого символа элементов. Так что это просто вопрос замены AlphaKeyGroup на StringKeyGroup.

Эту новую функциональность можно использовать как:

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;
    }
}
}  
person user2473408    schedule 11.06.2013

Чтобы использовать LongListSelector с числами, давайте попробуем сгруппировать список людей по возрасту, а не по первой букве их имени (в примере MSDN PeopleHub)

Они используют загадочную группу AlphaKeyGroup, которая представляет собой список людей, имена которых начинаются с одной и той же буквы (эта буква становится ключом группы AlphaKeyGroup). AlphaKeyGroups людей может выглядеть так:

  • Key = A: Amber, Amelia (где оба объекта People имеют имена, начинающиеся с A)
  • Key = B: Bob, Brian (где оба объекта People имеют имена, начинающиеся с B)
  • Клавиша = C: и т.д. и т.п.

Мы будем использовать IntegerKeyGroup, который представляет собой список людей одного возраста. IntegerKeyGroups людей может выглядеть так:

  • Ключ = 23: Дженнифер, Райан (где обоим объектам People по 23 года)
  • Ключ = 26: Эмбер, Меган (где обоим объектам «Люди» по 26 лет)
  • Ключ = 34: и т. д. и т. д.

Таким образом, чтобы следовать структуре GentryRiggen, мы должны сначала определить IntegerKeyGroup, а затем распределить людей по возрастным группам, к которым они принадлежат. Я поместил их в файл ViewModel.

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

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

Обратите внимание, что IntegerKeyGroup — это просто список, но со специальным целочисленным членом, который называется 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, сделайте список IntegerKeyGroups общедоступным с помощью функции CreateGroups.

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

Теперь в XAML внесите 1 изменение в исходный код из MSDN. Пример PeopleHub:

<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>

Это должно группировать людей по целым числам, в данном случае по возрасту.

person Vivian Liu - MSFT    schedule 26.06.2014