コード例 #1
0
        void setupRx(IEnumerable <T> initialContents = null, IScheduler scheduler = null, double resetChangeThreshold = 0.3)
        {
            if (rxObjectsSetup)
            {
                return;
            }

            scheduler = scheduler ?? RxApp.DeferredScheduler;
            _inner    = _inner ?? new List <T>();

            _changing = new Subject <NotifyCollectionChangedEventArgs>();
            _changing.Subscribe(raiseCollectionChanging);

            _changed = new Subject <NotifyCollectionChangedEventArgs>();
            _changed.Subscribe(raiseCollectionChanged);

            ResetChangeThreshold = resetChangeThreshold;

            _beforeItemsAdded   = new Lazy <Subject <T> >(() => new Subject <T>());
            _itemsAdded         = new Lazy <Subject <T> >(() => new Subject <T>());
            _beforeItemsRemoved = new Lazy <Subject <T> >(() => new Subject <T>());
            _itemsRemoved       = new Lazy <Subject <T> >(() => new Subject <T>());
            _itemChanging       = new Lazy <Subject <IObservedChange <T, object> > >(() => new Subject <IObservedChange <T, object> >());
            _itemChanged        = new Lazy <Subject <IObservedChange <T, object> > >(() => new Subject <IObservedChange <T, object> >());
            _beforeItemsMoved   = new Lazy <Subject <IMoveInfo <T> > >(() => new Subject <IMoveInfo <T> >());
            _itemsMoved         = new Lazy <Subject <IMoveInfo <T> > >(() => new Subject <IMoveInfo <T> >());

            // NB: We have to do this instead of initializing _inner so that
            // Collection<T>'s accounting is correct
            foreach (var item in initialContents ?? Enumerable.Empty <T>())
            {
                Add(item);
            }

            // NB: ObservableCollection has a Secret Handshake with WPF where
            // they fire an INPC notification with the token "Item[]". Emulate
            // it here
            CollectionCountChanging.Select(x => new PropertyChangingEventArgs("Count")).Subscribe(this.raisePropertyChanging);
            CollectionCountChanged.Select(x => new PropertyChangedEventArgs("Count")).Subscribe(this.raisePropertyChanged);
            Changing.Select(x => new PropertyChangingEventArgs("Item[]")).Subscribe(this.raisePropertyChanging);
            Changed.Select(x => new PropertyChangedEventArgs("Item[]")).Subscribe(this.raisePropertyChanged);

            rxObjectsSetup = true;
        }
コード例 #2
0
        void setupRx(IEnumerable <T> List = null)
        {
            _BeforeItemsAdded   = new ScheduledSubject <T>(RxApp.DeferredScheduler);
            _BeforeItemsRemoved = new ScheduledSubject <T>(RxApp.DeferredScheduler);
            aboutToClear        = new Subject <int>();
            cleared             = new Subject <int>();

            if (List != null)
            {
                foreach (var v in List)
                {
                    this.Add(v);
                }
            }

            var ocChangedEvent = new Subject <NotifyCollectionChangedEventArgs>();

            CollectionChanged += (o, e) => ocChangedEvent.OnNext(e);

            _ItemsAdded = ocChangedEvent
                          .Where(x =>
                                 x.Action == NotifyCollectionChangedAction.Add ||
                                 x.Action == NotifyCollectionChangedAction.Replace)
                          .SelectMany(x =>
                                      (x.NewItems != null ? x.NewItems.OfType <T>() : Enumerable.Empty <T>())
                                      .ToObservable())
                          .Multicast(new ScheduledSubject <T>(RxApp.DeferredScheduler))
                          .PermaRef();

            _ItemsRemoved = ocChangedEvent
                            .Where(x =>
                                   x.Action == NotifyCollectionChangedAction.Remove ||
                                   x.Action == NotifyCollectionChangedAction.Replace)
                            .SelectMany(x =>
                                        (x.OldItems != null ? x.OldItems.OfType <T>() : Enumerable.Empty <T>())
                                        .ToObservable())
                            .Multicast(new ScheduledSubject <T>(RxApp.DeferredScheduler))
                            .PermaRef();

            _CollectionCountChanging = Observable.Merge(
                _BeforeItemsAdded.Select(_ => this.Count),
                _BeforeItemsRemoved.Select(_ => this.Count),
                aboutToClear
                );

            _CollectionCountChanged = Observable.Merge(
                _ItemsAdded.Select(_ => this.Count),
                _ItemsRemoved.Select(_ => this.Count),
                cleared
                );

            _ItemChanging = new ScheduledSubject <IObservedChange <T, object> >(RxApp.DeferredScheduler);
            _ItemChanged  = new ScheduledSubject <IObservedChange <T, object> >(RxApp.DeferredScheduler);

            // TODO: Fix up this selector nonsense once SL/WP7 gets Covariance
            _Changing = Observable.Merge(
                _BeforeItemsAdded.Select <T, IObservedChange <object, object> >(x =>
                                                                                new ObservedChange <object, object>()
            {
                PropertyName = "Items", Sender = this, Value = this
            }),
                _BeforeItemsRemoved.Select <T, IObservedChange <object, object> >(x =>
                                                                                  new ObservedChange <object, object>()
            {
                PropertyName = "Items", Sender = this, Value = this
            }),
                aboutToClear.Select <int, IObservedChange <object, object> >(x =>
                                                                             new ObservedChange <object, object>()
            {
                PropertyName = "Items", Sender = this, Value = this
            }),
                _ItemChanging.Select <IObservedChange <T, object>, IObservedChange <object, object> >(x =>
                                                                                                      new ObservedChange <object, object>()
            {
                PropertyName = x.PropertyName, Sender = x.Sender, Value = x.Value
            }));

            _Changed = Observable.Merge(
                _ItemsAdded.Select <T, IObservedChange <object, object> >(x =>
                                                                          new ObservedChange <object, object>()
            {
                PropertyName = "Items", Sender = this, Value = this
            }),
                _ItemsRemoved.Select <T, IObservedChange <object, object> >(x =>
                                                                            new ObservedChange <object, object>()
            {
                PropertyName = "Items", Sender = this, Value = this
            }),
                _ItemChanged.Select <IObservedChange <T, object>, IObservedChange <object, object> >(x =>
                                                                                                     new ObservedChange <object, object>()
            {
                PropertyName = x.PropertyName, Sender = x.Sender, Value = x.Value
            }));

            _ItemsAdded.Subscribe(x => {
                this.Log().Debug("Item Added to {0:X} - {1}", this.GetHashCode(), x);
                if (propertyChangeWatchers == null)
                {
                    return;
                }
                addItemToPropertyTracking(x);
            });

            _ItemsRemoved.Subscribe(x => {
                this.Log().Debug("Item removed from {0:X} - {1}", this.GetHashCode(), x);
                if (propertyChangeWatchers == null || !propertyChangeWatchers.ContainsKey(x))
                {
                    return;
                }

                removeItemFromPropertyTracking(x);
            });

            IsEmpty = CollectionCountChanged.Select(x => x == 0);

#if DEBUG
            _ItemChanged.Subscribe(x =>
                                   this.Log().Debug("Object {0} changed in collection {1:X}", x, this.GetHashCode()));
#endif
        }