Ejemplo n.º 1
0
        /// <summary>
        /// Convert an observable collection into an observable change set
        /// </summary>
        /// <typeparam name="T">The type of the object.</typeparam>
        /// <typeparam name="TCollection"></typeparam>
        /// <param name="source">The source.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">source</exception>
        public static IObservable <IChangeSet <T> > ToObservableChangeSet <TCollection, T>(this TCollection source)
            where TCollection : INotifyCollectionChanged, IEnumerable <T>
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            return(Observable.Create <IChangeSet <T> >(observer =>
            {
                var data = new ChangeAwareList <T>(source);

                if (data.Count > 0)
                {
                    observer.OnNext(data.CaptureChanges());
                }

                return source.ObserveCollectionChanges()
                .Scan(data, (list, args) =>
                {
                    var changes = args.EventArgs;

                    switch (changes.Action)
                    {
                    case NotifyCollectionChangedAction.Add:
                        {
                            if (changes.NewItems.Count == 1)
                            {
                                list.Insert(changes.NewStartingIndex, (T)changes.NewItems[0]);
                            }
                            else
                            {
                                list.InsertRange(changes.NewItems.Cast <T>(), changes.NewStartingIndex);
                            }
                            break;
                        }

                    case NotifyCollectionChangedAction.Remove:
                        {
                            if (changes.OldItems.Count == 1)
                            {
                                list.RemoveAt(changes.OldStartingIndex);
                            }
                            else
                            {
                                list.RemoveRange(changes.OldStartingIndex, changes.OldItems.Count);
                            }
                            break;
                        }

                    case NotifyCollectionChangedAction.Replace:
                        {
                            list[changes.NewStartingIndex] = (T)changes.NewItems[0];
                            break;
                        }

                    case NotifyCollectionChangedAction.Reset:
                        {
                            list.Clear();
                            list.AddRange(source);
                            break;
                        }

                    case NotifyCollectionChangedAction.Move:
                        {
                            list.Move(changes.OldStartingIndex, changes.NewStartingIndex);
                            break;
                        }
                    }
                    return list;
                })
                .Select(list => list.CaptureChanges())
                .SubscribeSafe(observer);
            }));
        }