public InventoryViewModel(IObservableList <Shop> shops)
 {
     shops.Connect()
     .TransformMany(s => s.Products.Select(p => new InventoryItemViewModel(s, p)), new InventoryItemViewModelEqualityComparer())
     .Bind(out inventoryItems)
     .Subscribe();
 }
Example #2
0
        public IObservable <IChangeSet <T> > Run()
        {
            return(Observable.Create <IChangeSet <T> >(observer =>
            {
                Interlocked.Increment(ref _refCount);
                if (Volatile.Read(ref _refCount) == 1)
                {
                    Interlocked.Exchange(ref _list, _source.AsObservableList());
                }

                // ReSharper disable once PossibleNullReferenceException (never the case!)
                var subscriber = _list.Connect().SubscribeSafe(observer);

                return Disposable.Create(() =>
                {
                    Interlocked.Decrement(ref _refCount);
                    subscriber.Dispose();
                    if (Volatile.Read(ref _refCount) != 0)
                    {
                        return;
                    }
                    _list.Dispose();
                    Interlocked.Exchange(ref _list, null);
                });
            }));
        }
Example #3
0
        public IObservable <IChangeSet <T> > Run()
        {
            return(Observable.Create <IChangeSet <T> >(observer =>
            {
                lock (_locker)
                    if (++_refCount == 1)
                    {
                        _list = _source.AsObservableList();
                    }

                var subscriber = _list.Connect().SubscribeSafe(observer);

                return Disposable.Create(() =>
                {
                    subscriber.Dispose();
                    IDisposable listToDispose = null;
                    lock (_locker)
                        if (--_refCount == 0)
                        {
                            listToDispose = _list;
                            _list = null;
                        }
                    listToDispose?.Dispose();
                });
            }));
        }
        public IObservableListBindCacheSortedFixture()
        {
            _source = new SourceCache <Person, string>(p => p.Name);
            _sourceCacheNotifications = _source.Connect().AutoRefresh().Sort(_comparer, resetThreshold: 10).BindToObservableList(out _list).AsAggregator();

            _listNotifications = _list.Connect().AsAggregator();
        }
        public PagingListWithVirtualise(IObservableList <Animal> source, IObservable <IVirtualRequest> requests)
        {
            Virtualised = source.Connect()
                          .Virtualise(requests)
                          .AsObservableList();

            _cleanUp = Virtualised;
        }
Example #6
0
        public SimplePagging(IObservableList <Animal> source, IObservable <IPageRequest> pager)
        {
            Paged = source.Connect()
                    .Page(pager)
                    .Do(changes => Console.WriteLine(changes.TotalChanges)) //added as a quick and dirty way to debug
                    .AsObservableList();

            _cleanUp = Paged;
        }
        public StaticFilter(IObservableList <Animal> source)
        {
            //this list will automatically filter by Mammals only when the underlying list receives adds, or removes
            Mammals = source.Connect()
                      .Filter(animal => animal.Family == AnimalFamily.Mammal)
                      .AsObservableList();

            _cleanUp = Mammals;
        }
Example #8
0
        public IObservableListBindListFixture()
        {
            _source = new SourceList <Person>();
            _sourceListNotifications = _source
                                       .Connect()
                                       .AutoRefresh()
                                       .BindToObservableList(out _list)
                                       .AsAggregator();

            _observableListNotifications = _list.Connect().AsAggregator();
        }
Example #9
0
        public DynamicFilter(IObservableList <Animal> source, ISchedulerProvider schedulerProvider)
        {
            //produce an observable which creates a new predicate whenever AnimalFilter property changes
            var dynamicFilter = this.WhenValueChanged(@this => @this.AnimalFilter)
                                .Throttle(TimeSpan.FromMilliseconds(250), schedulerProvider.Background) //throttle to prevent constant filtering (i.e. when users type)
                                .Select(CreatePredicate);

            //Create list which automatically filters when AnimalFilter changes
            Filtered = source.Connect()
                       .Filter(dynamicFilter) //dynamicfilter can accept any predicate observable (i.e. does not have to be based on a property)
                       .AsObservableList();

            _cleanUp = Filtered;
        }
Example #10
0
        public SimulationListViewModel(IObservableList <SimulationRowViewModel> simulations, ReactiveUI.ReactiveCommand renderCommand)
        {
            if (simulations == null)
            {
                throw new ArgumentNullException(nameof(simulations));
            }

            simulations
            .Connect()
            .Bind(Simulations)
            .Subscribe();

            RenderCommand = renderCommand ?? throw new ArgumentNullException(nameof(renderCommand));
        }
Example #11
0
        public PropertyFilter(IObservableList <Animal> source, ISchedulerProvider schedulerProvider)
        {
            /*
             *  Create list which automatically filters:
             *
             * a) When the underlying list changes
             * b) When IncludeInResults property changes
             * c) NB: Add throttle when IncludeInResults properties can change in multiple animals in quick sucession
             *      (i.e. each time the prop changes the filter is re-assessed potentially leading to a flurry of updates - better to slow that down)
             */

            Filtered = source.Connect()
                       .FilterOnProperty(animal => animal.IncludeInResults, animal => animal.IncludeInResults, TimeSpan.FromMilliseconds(250), schedulerProvider.Background)
                       .AsObservableList();

            _cleanUp = Filtered;
        }
Example #12
0
        public ExternalSourceFilter(IObservableList <Animal> source, IObservableList <AnimalFamily> families)
        {
            /*
             *  Create list which is filtered from the result of another filter
             */

            var familyFilter = families.Connect()
                               .ToCollection()
                               .Select(items =>
            {
                bool Predicate(Animal animal) => items.Contains(animal.Family);
                return((Func <Animal, bool>)Predicate);
            });

            Filtered = source.Connect()
                       .Filter(familyFilter)
                       .AsObservableList();

            _cleanUp = Filtered;
        }
        public XamarinFormsGrouping(IObservableList <Animal> source, ISchedulerProvider schedulerProvider)
        {
            /* Xamarin forms is a bit dumb and cannot handle nested observable collections.
             * To cirumvent this limitation, create a specialist observable collection with headers and use dynamic data to manage it */

            //create an observable predicate
            var observablePredicate = this.WhenValueChanged(@this => @this.Filter).ObserveOn(schedulerProvider.Background);

            _cleanUp = source.Connect()
                       .Filter(observablePredicate)                                         //Apply filter dynamically
                       .GroupOn(arg => arg.Family)                                          //create a dynamic group
                       .Transform(grouping => new AnimalGroup(grouping, schedulerProvider)) //transform into a specialised observable collection
                       .Sort(SortExpressionComparer <AnimalGroup> .Ascending(a => a.Family))
                       .ObserveOn(schedulerProvider.MainThread)
                       .Bind(out var animals)
                       .DisposeMany()       //use DisposeMany() because the grouping is disposable
                       .Subscribe();

            FamilyGroups = animals;
        }
Example #14
0
        public ChangeComparer(IObservableList <int> source)
        {
            /*
             * Pass IObservable<IComparer<T>> into the sort operator to switch sorting
             *
             * The same concept applies to the ObservableCache
             */

            var optionChanged = this.WhenValueChanged(@this => @this.Option)
                                .Select(opt => opt == ChangeComparereOption.Ascending
                    ? SortExpressionComparer <int> .Ascending(i => i)
                    : SortExpressionComparer <int> .Descending(i => i));

            //create a sorted observable list
            DataSource = source.Connect()
                         .Sort(optionChanged)
                         .AsObservableList();

            _cleanUp = DataSource;
        }
Example #15
0
        public DataGridViewModel(List <DataTableColumn> dataColumns, IObservableList <DataTableRow> data, OutputModeOption outputMode)
        {
            var columns = dataColumns.Select(x => new Column(x));

            Columns.AddRange(columns);

            SelectionMode = OutputModeToSelectionMode(outputMode);

            this.WhenActivated((CompositeDisposable disposables) =>
            {
                Columns.Connect()
                .AutoRefresh()
                .ObserveOn(RxApp.MainThreadScheduler)
                .Bind(out _columnSelect)
                .Subscribe();

                data.Connect()
                .Bind(out _viewObjects)
                .Subscribe();
            });
        }
        public DerivedProgressionManager(IObservableList <IProgressionViewer> subProgs, ILoggerFactory loggerFactory)
        {
            this.logger = loggerFactory.CreateLogger <DerivedProgressionManager>();
            subProgs
            .Connect()
            .ToCollection()
            .Select(progs => progs.Select(prog => prog.WhenAnyValue(
                                              vm => vm.Title,
                                              vm => vm.State,
                                              vm => vm.Target,
                                              vm => vm.Current,
                                              vm => vm.Details,
                                              vm => vm.Weight,
                                              ProgressionSnapshot.Factory)))
            .Select(Observable.CombineLatest)
            .Switch()
            .Subscribe(progs =>
            {
                this.State = JobStateHelper.MergeStates(progs.Select(prog => prog.State));
                Target     = progs.Sum(prog => prog.Weight) * Resolution;

                Current = (int)progs.Sum(prog => (decimal)prog.Current / (decimal)prog.Target * Weight * Resolution);

                var newDetails = progs.FirstOrDefault(x => x.State == JobState.InProgress).Details;
                if (State.IsIn(JobState.ToDo, JobState.Done))
                {
                    newDetails = string.Empty;
                }
                if (State == JobState.Failed)
                {
                    newDetails = $"Job Failed.{Environment.NewLine + progs.FirstOrDefault(x => x.State == JobState.Failed).Details}";
                    logger.LogError("job failed: {0}", newDetails);
                }
                Details = newDetails;
                logger.LogTrace("extra info:" + subProgs.Count + Environment.NewLine +
                                string.Join(Environment.NewLine, progs.Select(prog => $" {prog.Title} | {prog.State} | {prog.Current}/{prog.Target} : {prog.Details}"))
                                );
                logger.LogTrace("updating progress - {0}subs: {1}/{2} ({3}): {4}", progs.Count(), Current, Target, State, Details);
            });
        }
Example #17
0
        public void SetTagpool(IObservableList <Tag> tagpool)
        {
            tagpoolReset.OnNext(new Unit());
            Tagpool = tagpool;



            Tagpool
            .Connect()
            .Filter(
                NewTagChanges.Select <string, Func <Tag, bool> >(
                    newTag => tag => ((string)tag).ToLower().Contains(newTag.ToLower())
                    )
                )
            .Except(TagpoolExceptions)
            .Transform(tag => new TagEx(tag, true))
            .Merge(
                CompletePoolChanges
                .DistinctUntilChanged()
                .Select(completePool =>
                        completePool
                                ? allTags
                        .Except(
                            TagpoolExceptions.Merge(
                                Selection.Connect()))
                        .Transform(tag => new TagEx(tag, false))
                                : Observable.Empty <IChangeSet <TagEx> >()
                        )
                .Switch()
                )
            //.Sort()
            .ObserveOn(RxApp.MainThreadScheduler)
            .Bind(TagpoolBinding)
            .TakeUntil(tagpoolReset)
            .TakeUntil(destroy)
            .Subscribe(_ => { }, ex =>
            {
                MessageBox.Show($"({GetType().FullName}) tagpool exception: " + Environment.NewLine + ex.ToString());
            });
        }
Example #18
0
        public Aggregations(IObservableList <int> source)
        {
            /*
             * Available aggregations: Max, Min, Avg, StdDev, Count, Sum.
             *
             * For custom aggregations use: source.Connect().ToCollection().Select(items=>...);
             */
            var shared = source.Connect()
                         //by default dd never notifies when the change set is empty i.e. upon subscripion when the source has no data
                         //this means that no result is computed until data is loaded. However if you require a result even when the data source is empty, use StartWithEmpty()
                         .StartWithEmpty()
                         //use standard rx Publish() / Connect() to share published changesets
                         .Publish();

            _cleanUp = new CompositeDisposable
                       (
                shared.Maximum(i => i).Subscribe(max => Max = max),
                shared.Minimum(i => i).Subscribe(min => Min = min),
                shared.Avg(i => i).Subscribe(avg => Avg     = avg),

                shared.Connect()
                       );
        }
Example #19
0
        public IObservable <IChangeSet <T> > Run()
        {
            int refCount             = 0;
            var locker               = new object();
            IObservableList <T> list = null;

            return(Observable.Create <IChangeSet <T> >(observer =>
            {
                lock (locker)
                {
                    refCount++;
                    if (refCount == 1)
                    {
                        list = _source.AsObservableList();
                    }

                    // ReSharper disable once PossibleNullReferenceException (never the case!)
                    var subscriber = list.Connect().SubscribeSafe(observer);

                    return Disposable.Create(() =>
                    {
                        lock (locker)
                        {
                            refCount--;
                            subscriber.Dispose();
                            if (refCount != 0)
                            {
                                return;
                            }
                            list.Dispose();
                            list = null;
                        }
                    });
                }
            }));
        }
Example #20
0
        public IObservable <IChangeSet <TObject, TKey> > Run()
        {
            return(Observable.Create <IChangeSet <TObject, TKey> >(
                       observer =>
            {
                var locker = new object();

                // this is the resulting cache which produces all notifications
                var resultCache = new ChangeAwareCache <TObject, TKey>();

                // Transform to a merge container.
                // This populates a RefTracker when the original source is subscribed to
                var sourceLists = _source.Connect().Synchronize(locker).Transform(changeSet => new MergeContainer(changeSet)).AsObservableList();

                var sharedLists = sourceLists.Connect().Publish();

                // merge the items back together
                var allChanges = sharedLists.MergeMany(mc => mc.Source).Synchronize(locker).Subscribe(
                    changes =>
                {
                    // Populate result list and check for changes
                    UpdateResultList(resultCache, sourceLists.Items.AsArray(), changes);

                    var notifications = resultCache.CaptureChanges();
                    if (notifications.Count != 0)
                    {
                        observer.OnNext(notifications);
                    }
                });

                // when an list is removed, need to
                var removedItem = sharedLists.OnItemRemoved(
                    mc =>
                {
                    // Remove items if required
                    ProcessChanges(resultCache, sourceLists.Items.AsArray(), mc.Cache.KeyValues);

                    if (_type == CombineOperator.And || _type == CombineOperator.Except)
                    {
                        var itemsToCheck = sourceLists.Items.SelectMany(mc2 => mc2.Cache.KeyValues);
                        ProcessChanges(resultCache, sourceLists.Items.AsArray(), itemsToCheck);
                    }

                    var notifications = resultCache.CaptureChanges();
                    if (notifications.Count != 0)
                    {
                        observer.OnNext(notifications);
                    }
                }).Subscribe();

                // when an list is added or removed, need to
                var sourceChanged = sharedLists.WhereReasonsAre(ListChangeReason.Add, ListChangeReason.AddRange).ForEachItemChange(
                    mc =>
                {
                    ProcessChanges(resultCache, sourceLists.Items.AsArray(), mc.Current.Cache.KeyValues);

                    if (_type == CombineOperator.And || _type == CombineOperator.Except)
                    {
                        ProcessChanges(resultCache, sourceLists.Items.AsArray(), resultCache.KeyValues.ToArray());
                    }

                    var notifications = resultCache.CaptureChanges();
                    if (notifications.Count != 0)
                    {
                        observer.OnNext(notifications);
                    }
                }).Subscribe();

                return new CompositeDisposable(sourceLists, allChanges, removedItem, sourceChanged, sharedLists.Connect());
            }));
        }
Example #21
0
        public async Task TestFilterOnProperty()
        {
            var listA = new SourceList <X>();
            var listB = new SourceList <X>();

            using (IObservableList <X> list = listA.Connect()
                                              .Or(listB.Connect())
                                              .AsObservableList())
            {
                var nameA1 = "A1";
                var a1     = new X(nameA1);
                var a2     = new X("A2");
                listA.Edit(l =>
                {
                    l.Clear();
                    l.Add(a1);
                    l.Add(a2);
                });

                var b1 = new X("B1");
                var b2 = new X("B2");
                listB.Edit(l =>
                {
                    l.Clear();
                    l.Add(b1);
                    l.Add(b2);
                });

                Assert.AreEqual(4, list.Count);

                int count = await list.CountChanged.FirstAsync();

                Assert.AreEqual(4, count);

                IObservable <IChangeSet <X> > obsFiltered = list.Connect()
                                                            .FilterOnProperty(v => v.IsConnected, v => v.IsConnected);

                using (IObservableList <X> obsFilteredAsList = obsFiltered.AsObservableList())
                {
                    IObservable <IChangeSet <XVm> > obsTransformed = obsFiltered
                                                                     .Transform(v => new XVm(v))
                                                                     .DisposeMany();

                    var ctorCount = 0;
                    var dtorCount = 0;
                    using (IObservableList <XVm> obsTransformedAsList = obsTransformed.AsObservableList())
                    {
                        ctorCount += 4;

                        Assert.That(obsFilteredAsList.Items.Contains(a1));
                        Assert.That(obsFilteredAsList.Items.Count(), Is.EqualTo(obsTransformedAsList.Items.Count()));

                        a1.IsConnected = false;
                        Assert.That(obsFilteredAsList.Items, Has.No.Member(a1));
                        dtorCount++;
                        Assert.That(XVm.Constructed, Is.EqualTo(ctorCount));
                        Assert.That(XVm.Destructed, Is.EqualTo(dtorCount));

                        a1.IsConnected = true;
                        Assert.That(obsFilteredAsList.Items, Has.Member(a1));
                        ctorCount++;
                        Assert.That(XVm.Constructed, Is.EqualTo(ctorCount));
                        Assert.That(XVm.Destructed, Is.EqualTo(dtorCount));

                        Console.WriteLine("--remove");
                        listA.Remove(a1);
                        dtorCount++;
                        Assert.That(XVm.Constructed, Is.EqualTo(ctorCount));
                        Assert.That(XVm.Destructed, Is.EqualTo(dtorCount));

                        Console.WriteLine("--add");
                        listA.Add(a1);
                        ctorCount++;
                        Assert.That(XVm.Constructed, Is.EqualTo(ctorCount));
                        Assert.That(XVm.Destructed, Is.EqualTo(dtorCount));

                        Console.WriteLine("--clear");
                        listA.Clear();
                        dtorCount += 2; //FIX:  List A contains 2 items (was adding 4)
                        Assert.That(XVm.Constructed, Is.EqualTo(ctorCount));
                        Assert.That(XVm.Destructed, Is.EqualTo(dtorCount));

                        Console.WriteLine("--add");

                        //FIX: Maybe a debate required!  List B already contains b1, so not regarded as a new item in the Or result
                        Debug.Assert(listB.Items.Contains(b1));
                        listA.Add(b1);
                        //  ctorCount++;
                        Assert.That(XVm.Constructed, Is.EqualTo(ctorCount));
                        Assert.That(XVm.Destructed, Is.EqualTo(dtorCount));

                        Console.WriteLine("--disp");
                    }
                    dtorCount += 2; //FIX: Should be +3 s this is what
                    Assert.That(XVm.Constructed, Is.EqualTo(ctorCount));
                    Assert.That(XVm.Destructed, Is.EqualTo(dtorCount));
                }
            }
        }