public virtual GroupCollection <T> Perform( IReadOnlyCollection <T> items, int level, Group <T> parent) { GroupDescriptorCollection groupDescriptors = this.index.CollectionView.GroupDescriptors; if (level >= groupDescriptors.Count) { return(GroupCollection <T> .Empty); } IGroupFactory <T> groupFactory = this.index.CollectionView.GroupFactory; GroupCollection <T> cachedGroups = this.GetCachedGroups(items, level); if (!GroupBuilder <T> .IsValid(level, groupDescriptors)) { cachedGroups?.Dispose(); return(groupFactory.CreateCollection((IList <Group <T> >)GroupBuilder <T> .Empty)); } IComparer <Group <T> > comparer = Activator.CreateInstance(this.Comparer.GetType()) as IComparer <Group <T> > ?? this.Comparer; if (comparer is GroupComparer <T> ) { ((GroupComparer <T>)comparer).Directions = this.GetComparerDirections(level); } AvlTree <Group <T> > avlTree1 = new AvlTree <Group <T> >(comparer); AvlTree <Group <T> > avlTree2 = new AvlTree <Group <T> >((IComparer <Group <T> >) new GroupComparer <T>(this.GetComparerDirections(level))); foreach (T key1 in !this.CollectionView.CanPage || level != 0 || !this.CollectionView.PagingBeforeGrouping ? (IEnumerable <T>)items : (IEnumerable <T>) this.index.GetItemsOnPage(this.CollectionView.PageIndex)) { object key2 = this.GroupPredicate(key1, level); Group <T> group1 = (Group <T>) new DataItemGroup <T>(key2); Group <T> group2 = avlTree2.Find(group1); if (group2 == null) { group2 = this.GetGroup(cachedGroups, group1, parent, key2, level); avlTree2.Add(group2); } group2.Items.Add(key1); if (this.itemGroupsCache.ContainsKey(key1)) { this.itemGroupsCache[key1] = group2; } else { this.itemGroupsCache.Add(key1, group2); } } for (int index = 0; index < avlTree2.Count; ++index) { avlTree1.Add(avlTree2[index]); } cachedGroups?.Dispose(); return(groupFactory.CreateCollection((IList <Group <T> >)avlTree1)); }
/// <summary> /// Performs the grouping operation for specified items. /// </summary> /// <param name="items">The items.</param> /// <param name="level">The level.</param> /// <param name="parent">The parent.</param> /// <returns></returns> public virtual GroupCollection <T> Perform(IReadOnlyCollection <T> items, int level, Group <T> parent) { GroupDescriptorCollection groupDescriptors = this.index.CollectionView.GroupDescriptors; if (level >= groupDescriptors.Count) { return(GroupCollection <T> .Empty); } IGroupFactory <T> groupFactory = this.index.CollectionView.GroupFactory; GroupCollection <T> cache = GetCachedGroups(items, level); if (!IsValid(level, groupDescriptors)) { if (cache != null) { cache.Dispose(); } return(this.index.CollectionView.GroupFactory.CreateCollection(GroupBuilder <T> .Empty)); } IComparer <Group <T> > newComparer = Activator.CreateInstance(this.Comparer.GetType()) as IComparer <Group <T> >; if (newComparer == null) { newComparer = this.Comparer; } if (newComparer is GroupComparer <T> ) { ((GroupComparer <T>)newComparer).Directions = this.GetComparerDirections(level); } AvlTree <Group <T> > groupList = new AvlTree <Group <T> >(newComparer); AvlTree <Group <T> > list = new AvlTree <Group <T> >(new GroupComparer <T>(this.GetComparerDirections(level))); foreach (T item in items) { object key = this.GroupPredicate(item, level); Group <T> group, newGroup = new DataItemGroup <T>(key); group = list.Find(newGroup); groupList.Find(newGroup); if (group == null) { group = GroupBuilder <T> .GetCachedGroup(cache, newGroup); if (group == null) { group = groupFactory.CreateGroup(key, parent); DataItemGroup <T> dataGroup = group as DataItemGroup <T>; dataGroup.GroupBuilder = this; } list.Add(group);// groupList.Add(group); } group.Items.Add(item); } for (int i = 0; i < list.Count; i++) { groupList.Add(list[i]); } if (cache != null) { cache.Dispose(); } return(groupFactory.CreateCollection(groupList)); }