Ejemplo n.º 1
0
        private IChangeSet <IGrouping <TObject, TGroupKey> > Process(ChangeAwareList <IGrouping <TObject, TGroupKey> > result, IDictionary <TGroupKey, GroupContainer> allGroupings, IChangeSet <ItemWithGroupKey> changes)
        {
            //need to keep track of effected groups to calculate correct notifications
            var initialStateOfGroups = new Dictionary <TGroupKey, IGrouping <TObject, TGroupKey> >();

            foreach (var grouping in Enumerable.GroupBy(changes.Unified(), change => change.Current.Group))
            {
                //lookup group and if created, add to result set
                var currentGroup   = grouping.Key;
                var groupContainer = GetGroup(allGroupings, currentGroup);

                void GetInitialState()
                {
                    if (!initialStateOfGroups.ContainsKey(grouping.Key))
                    {
                        initialStateOfGroups[grouping.Key] = GetGroupState(groupContainer);
                    }
                }

                var listToModify = groupContainer.List;

                //iterate through the group's items and process
                foreach (var change in grouping)
                {
                    switch (change.Reason)
                    {
                    case ListChangeReason.Add:
                    {
                        GetInitialState();
                        listToModify.Add(change.Current.Item);
                        break;
                    }

                    case ListChangeReason.Refresh:
                    {
                        var previousItem  = change.Current.Item;
                        var previousGroup = change.Current.PrevousGroup.Value;
                        var currentItem   = change.Current.Item;

                        //check whether an item changing has resulted in a different group
                        if (!previousGroup.Equals(currentGroup))
                        {
                            GetInitialState();
                            //add to new group
                            listToModify.Add(currentItem);

                            //remove from old group
                            allGroupings.Lookup(previousGroup)
                            .IfHasValue(g =>
                                {
                                    if (!initialStateOfGroups.ContainsKey(g.Key))
                                    {
                                        initialStateOfGroups[g.Key] = GetGroupState(g.Key, g.List);
                                    }

                                    g.List.Remove(previousItem);
                                });
                        }
                        break;
                    }

                    case ListChangeReason.Replace:
                    {
                        GetInitialState();
                        var previousItem  = change.Previous.Value.Item;
                        var previousGroup = change.Previous.Value.Group;

                        //check whether an item changing has resulted in a different group
                        if (previousGroup.Equals(currentGroup))
                        {
                            //find and replace
                            var index = listToModify.IndexOf(previousItem);
                            listToModify[index] = change.Current.Item;
                        }
                        else
                        {
                            //add to new group
                            listToModify.Add(change.Current.Item);

                            //remove from old group
                            allGroupings.Lookup(previousGroup)
                            .IfHasValue(g =>
                                {
                                    if (!initialStateOfGroups.ContainsKey(g.Key))
                                    {
                                        initialStateOfGroups[g.Key] = GetGroupState(g.Key, g.List);
                                    }

                                    g.List.Remove(previousItem);
                                });
                        }
                        break;
                    }

                    case ListChangeReason.Remove:
                    {
                        GetInitialState();
                        listToModify.Remove(change.Current.Item);
                        break;
                    }

                    case ListChangeReason.Clear:
                    {
                        GetInitialState();
                        listToModify.Clear();
                        break;
                    }
                    }
                }
            }
            return(CreateChangeSet(result, allGroupings, initialStateOfGroups));
        }