Search code examples
linqwindows-phone-8longlistselector

Correct implementation of IGrouping to be used inside longlistselector groupheader


I have an ObservableCollection like the following-

    private ObservableCollection<KeyedList<int, Anime>> _grp;
    public ObservableCollection<KeyedList<int, Anime>> GroupedAnimeByGenre
    {
        get
        {
            return _grp;

        }
        set
        {
            _grp = value;
            RaisePropertyChanged("GroupedAnimeByGenre");
        }
    }

I am using this to populate a LongListSelector with grouping. The KeyedList is implemented like this-

public class KeyedList<TKey, TItem> : List<TItem>
{
    public TKey Key { protected set; get; }

    public KeyedList(TKey key, IEnumerable<TItem> items)
        : base(items)
    {
        Key = key;
    }

    public KeyedList(IGrouping<TKey, TItem> grouping)
        : base(grouping)
    {
        Key = grouping.Key;
    }
}

I have the following code to feed the ObservableCollection. Keep in mind AnimeList2 is a temporary Collection.

 var groupFinale = AnimeList2.GroupBy(txt => txt.id).Where(grouping => grouping.Count() > 1).ToObservableCollection();

 GroupedAnimeByGenre = groupFinale ;

But I am unable to convert/use groupFinale with GroupedAnimeByGenre. I am missing the extension method part as I am not well aware of the syntax. Please help


Solution

  • If you remove the ToObservableCollection() call and take just that part

    var groupFinale = AnimeList2.GroupBy(txt => txt.id).Where(grouping => grouping.Count() > 1);
    

    you'll see that the type of groupFinale is IEnumerable<IGrouping<int, Anime>>. Hence applying ToObservableCollection() will result in ObservableCollection<IGrouping<int, Anime>>. However, the type of the GroupedAnimeByGenre is ObservableCollection<KeyedList<int, Anime>>. So you need to convert IEnumerable<IGrouping<int, Anime>> to IEnumerable<KeyedList<int, Anime>> which in LINQ is performed by the Select method.

    Shortly, you can use something like this

    var groupFinale = AnimeList2
        .GroupBy(txt => txt.id)
        .Where(grouping => grouping.Count() > 1)
        .Select(grouping => new KeyedList<int, Anime>(grouping))
        .ToObservableCollection();
    

    You can make such conversion easier by providing an extension method (similar to BCL provided ToArray() / ToList()) that will allow skipping the type arguments like this

    public static class KeyedList
    {
        public static KeyedList<TKey, TItem> ToKeyedList<TKey, TItem>(this IGrouping<TKey, TItem> source)
        {
            return new KeyedList<TKey, TItem>(source); 
        }
    }
    

    Then you can use simply

    var groupFinale = AnimeList2
        .GroupBy(txt => txt.id)
        .Where(grouping => grouping.Count() > 1)
        .Select(grouping => grouping.ToKeyedList())
        .ToObservableCollection();