Пример #1
0
        public void DoNotThrowAWobblyWhenRemovingaMutatedValue()
        {

            var pageController = new PageController();
            var sortController = new SortController<TestVm>(SortExpressionComparer<TestVm>.Ascending(t => t.DateFavorited ?? DateTime.MinValue));
            var filterController = new FilterController<TestVm>(myVm => myVm.Id != 0);
            var items = new ObservableCollectionExtended<TestVm>();
            var itemCache = new SourceCache<TestVm, int>(myVm => myVm.Id);

            var item1 = new TestVm(1) { DateFavorited = DateTime.Now };
            var item2 = new TestVm(2) { DateFavorited = DateTime.Now };

            itemCache.AddOrUpdate(item1);
            itemCache.AddOrUpdate(item2);

            bool error = false;
            itemCache.Connect()
                .Filter(filterController)
                .Sort(sortController)
                .Page(pageController)//error doesnt occur with paging disabled
                .Bind(items)
                .Subscribe(changes => { }, ex => error = true);

            pageController.Change(new PageRequest(1, 100));

            //NB: never errored if it was the first item which was removed
            item2.DateFavorited = null;
            itemCache.Remove(item2); //ERROR!

            Assert.IsFalse(error, "Error has been thrown");
        }
        public void InlineChanges()
        {
            var people = _generator.Take(10000).ToArray();
            _cache.BatchUpdate(updater => updater.AddOrUpdate(people));

            //apply mutable changes to the items
            var random = new Random();
            var tochange = people.OrderBy(x => Guid.NewGuid()).Take(10).ToList();

            tochange.ForEach(p => p.Age = random.Next(0, 100));

               // _sortController.Resort();

               _cache.Evaluate(tochange);

            var expected = people.OrderBy(t=>t,_comparer).ToList();
            var actual = _results.Messages.Last().SortedItems.Select(kv=>kv.Value).ToList();
            CollectionAssert.AreEqual(expected,actual);

            var list = new ObservableCollectionExtended<Person>();
            var adaptor = new SortedObservableCollectionAdaptor<Person, string>();
            foreach (var message in _results.Messages)
            {
                adaptor.Adapt(message, list);
            }
            CollectionAssert.AreEquivalent(expected, list);
        }
        public void SetUp()
        {
            _collection = new ObservableCollectionExtended<Person>();
            _source = new SourceCache<Person, string>(p => p.Name);
            _binder = _source.Connect()
                .Sort(_comparer,resetThreshold:25)
                .Bind(_collection)
                .Subscribe();

        }
 public void ExtendedObservableCollection_RemoveNullHandlerTest()
 {
     using (var verify = new Verify())
     {
         var list = new ObservableCollectionExtended<int>();
         var result = new ReadOnlyObservableCollectionExtended<int>(list);
         verify.ArgumentNullException("eventHandler", () => result.RemoveHandler((IListener<NotifyCollectionChangedEventArgs>)null));
         verify.ArgumentNullException("eventHandler", () => result.RemoveHandler((IListener<PropertyChangedEventArgs>)null));
     }
 }
        public void ExtendedObservableCollection_AddRange_Test1()
        {
            using (var verify = new Verify())
            {
                var weakNotifier = new WeakNotifier();
                var notifier = new Notifier();
                var temp = new[] { notifier, weakNotifier };

                var result = new ObservableCollectionExtended<object>();
                result.AddRange(temp);
                ConstructorAssertions(verify, result, weakNotifier, notifier);
            }
        }
 public void ExtendedObservableCollection_AddRange_Test2()
 {
     using (var verify = new Verify())
     {
         try
         {
             var result = new ObservableCollectionExtended<object>();
             result.AddRange(null);
             verify.Fail("Expected an ArgumentNullException exception");
         }
         catch (ArgumentNullException ex)
         {
             verify.AreEqual("list", ex.ParamName, "Parameter name is incorrect");
         }
     }
 }
        public void ExtendedObservableDictionary_RemoveHandlerTest2()
        {
            using (var verify = new Verify())
            {
                var list = new ObservableCollectionExtended<int>();
                var result = new ReadOnlyObservableCollectionExtended<int>(list);

                var collectionChangedEventQueue = new Queue<Tuple<object, NotifyCollectionChangedEventArgs>>();
                var collectionChangedListener = new Listener<NotifyCollectionChangedEventArgs>((s, e) => collectionChangedEventQueue.Enqueue(Tuple.Create(s, e)));
                result.AddHandler(collectionChangedListener);
                result.RemoveHandler(collectionChangedListener);
                result.RemoveHandler(collectionChangedListener);

                var propertyChangedEventQueue = new Queue<Tuple<object, PropertyChangedEventArgs>>();
                var propertyChangedListener = new Listener<PropertyChangedEventArgs>((s, e) => propertyChangedEventQueue.Enqueue(Tuple.Create(s, e)));
                result.AddHandler(propertyChangedListener);
                result.RemoveHandler(propertyChangedListener);
                result.RemoveHandler(propertyChangedListener);

            }
        }
Пример #8
0
 public TestFixture()
 {
     TestCollection = new ObservableCollectionExtended <int>();
 }
Пример #9
0
        public SearchOptionsViewModel(ISearchMetadataCollection metadataCollection,
                                      ISearchMetadataFactory searchMetadataFactory,
                                      ISchedulerProvider schedulerProvider,
                                      IColourProvider colourProvider,
                                      IIconProvider iconsProvider,
                                      ITextAssociationCollection textAssociationCollection,
                                      SearchHints searchHints,
                                      IThemeProvider themeProvider)
        {
            SearchHints = searchHints;

            var proxyItems = metadataCollection.Metadata.Connect()
                             .WhereReasonsAre(ChangeReason.Add, ChangeReason.Remove) //ignore updates because we update from here
                             .Transform(meta =>
            {
                return(new SearchOptionsProxy(meta,
                                              colourProvider,
                                              themeProvider,
                                              new IconSelector(iconsProvider, schedulerProvider),
                                              m => metadataCollection.Remove(m.SearchText),
                                              iconsProvider.DefaultIconSelector,
                                              Id));
            })
                             .SubscribeMany(so =>
            {
                //when a value changes, write the original value back to the metadata collection
                var anyPropertyHasChanged = so.WhenAnyPropertyChanged()
                                            .Select(_ => (SearchMetadata)so)
                                            .Subscribe(metadataCollection.AddorUpdate);

                //when an icon or colour has changed we need to record user choice so
                //the same choice can be used again
                var iconChanged       = so.WhenValueChanged(proxy => proxy.IconKind, false).ToUnit();
                var colourChanged     = so.WhenValueChanged(proxy => proxy.HighlightHue, false).ToUnit();
                var ignoreCaseChanged = so.WhenValueChanged(proxy => proxy.IgnoreCase, false).ToUnit();

                var textAssociationChanged = iconChanged.Merge(colourChanged).Merge(ignoreCaseChanged)
                                             .Throttle(TimeSpan.FromMilliseconds(250))
                                             .Select(_ => new TextAssociation(so.Text, so.IgnoreCase, so.UseRegex, so.HighlightHue.Swatch, so.IconKind.ToString(), so.HighlightHue.Name, DateTime.UtcNow))
                                             .Subscribe(textAssociationCollection.MarkAsChanged);

                return(new CompositeDisposable(anyPropertyHasChanged, textAssociationChanged));
            })
                             .AsObservableCache();

            var monitor = MonitorPositionalChanges()
                          .Subscribe(metadataCollection.Add);


            //load data onto grid
            var collection = new ObservableCollectionExtended <SearchOptionsProxy>();

            var userOptions = proxyItems.Connect()
                              .Sort(SortExpressionComparer <SearchOptionsProxy> .Ascending(proxy => proxy.Position))
                              .ObserveOn(schedulerProvider.MainThread)
                              //force reset for each new or removed item dues to a bug in the underlying dragablz control which inserts in an incorrect position
                              .Bind(collection, new ObservableCollectionAdaptor <SearchOptionsProxy, string>(0))
                              .DisposeMany()
                              .Subscribe();

            Data = new ReadOnlyObservableCollection <SearchOptionsProxy>(collection);

            //command to add the current search to the tail collection
            var searchInvoker = SearchHints.SearchRequested
                                .ObserveOn(schedulerProvider.Background)
                                .Subscribe(request =>
            {
                var meta = searchMetadataFactory.Create(request.Text,
                                                        request.UseRegEx,
                                                        metadataCollection.NextIndex(),
                                                        false);
                metadataCollection.AddorUpdate(meta);
            });

            _cleanUp = new CompositeDisposable(searchInvoker,
                                               userOptions,
                                               searchInvoker,
                                               monitor,
                                               SearchHints);
        }
        private static void ConstructorAssertions(Verify verify, ObservableCollectionExtended<object> result, WeakNotifier weakNotifier, Notifier notifier)
        {
            var itemAssert = new ItemPropertyChangedEventTest(verify, result);

            var itemAddedEventQueue = new Queue<Tuple<object, ItemEventArgs<object>>>();
            result.ItemAdded += (s, e) => itemAddedEventQueue.Enqueue(Tuple.Create(s, e));

            var itemRemovedEventQueue = new Queue<Tuple<object, ItemEventArgs<object>>>();
            result.ItemRemoved += (s, e) => itemRemovedEventQueue.Enqueue(Tuple.Create(s, e));

            weakNotifier.Age += 1;
            itemAssert.ExpectEvent(weakNotifier, "Age");

            notifier.Age += 1;
            itemAssert.ExpectEvent(notifier, "Age");

            var oldCount = result.Count;
            result.Clear();
            verify.AreEqual(oldCount, itemRemovedEventQueue.Count, "incorrect number of items reported as being removed");

            weakNotifier.Age += 1;
            notifier.Age += 1;

            verify.AreEqual(0, result.Count, "The collection should be empty");
            itemAssert.ExpectCountEquals(0, "ItemPropertyChanged events were fired when the collection was supposed to be empty.");

            result.Add(weakNotifier);
            result.Add(notifier);
            verify.AreEqual(2, result.Count, "The new items were not added");
            verify.AreEqual(2, itemAddedEventQueue.Count, "The new item events didn't fire");
            CollectionAssert.AreEqual(result, result.ReadOnlyWrapper);

            itemRemovedEventQueue.Clear();
            result.RemoveAt(0);
            verify.AreEqual(1, itemRemovedEventQueue.Count, "the item wasn't removed");
            verify.AreSame(notifier, result[0], "the wrong item was removed");
            CollectionAssert.AreEqual(result, result.ReadOnlyWrapper);

            itemAddedEventQueue.Clear();
            itemRemovedEventQueue.Clear();
            result[0] = weakNotifier;
            verify.AreSame(weakNotifier, result[0], "the item wasn't updated");
            verify.AreEqual(1, itemAddedEventQueue.Count, "the add event for replacing an item didn't fire");
            verify.AreEqual(1, itemRemovedEventQueue.Count, "the remove event for replacing an item didn't fire");
            CollectionAssert.AreEqual(result, result.ReadOnlyWrapper);
        }
        public void ExtendedObservableCollection_MemoryTest1()
        {
            using (var verify = new Verify())
            {
                Func<WeakReference> builder = () =>
                {

                    var result = new ObservableCollectionExtended<object>();
                    var weakNotifier = new WeakNotifier();
                    result.Add(weakNotifier);

                    return new WeakReference(result);
                };

                var wr = builder();

                Memory.CycleGC();

                verify.IsFalse(wr.IsAlive, "An item in the collection is preventing the collection from being collected");
            }
        }
        public void ExtendedObservableCollection_ConstructorTest1()
        {
            using (var verify = new Verify())
            {
                var result = new ObservableCollectionExtended<object>();
                result.Add(1);
                result.Add("Boat");

                var weakNotifier = new WeakNotifier();
                var notifier = new Notifier();

                result.Add(weakNotifier);
                result.Add(notifier);

                ConstructorAssertions(verify, result, weakNotifier, notifier);
            }
        }
 public BindFromObservableListFixture()
 {
     _collection = new ObservableCollectionExtended <Person>();
     _source     = new SourceList <Person>();
     _binder     = _source.Connect().Bind(_collection).Subscribe();
 }
Пример #14
0
        public SearchOptionsViewModel(ISearchMetadataCollection metadataCollection,
            ISearchMetadataFactory searchMetadataFactory,
            ISchedulerProvider schedulerProvider,
            IColourProvider colourProvider,
            IIconProvider iconsProvider,
            ITextAssociationCollection textAssociationCollection,
            SearchHints searchHints,
            IThemeProvider themeProvider)
        {
            SearchHints = searchHints;

            var proxyItems = metadataCollection.Metadata.Connect()
                .WhereReasonsAre(ChangeReason.Add, ChangeReason.Remove) //ignore updates because we update from here
                .Transform(meta =>
                {
                    return new SearchOptionsProxy(meta,
                        colourProvider,
                        themeProvider,
                        new IconSelector(iconsProvider, schedulerProvider),
                        m => metadataCollection.Remove(m.SearchText),
                        iconsProvider.DefaultIconSelector,
                        Id);
                })
                .SubscribeMany(so =>
                {
                    //when a value changes, write the original value back to the metadata collection
                    var anyPropertyHasChanged = so.WhenAnyPropertyChanged()
                        .Select(_ => (SearchMetadata) so)
                        .Subscribe(metadataCollection.AddorUpdate);

                    //when an icon or colour has changed we need to record user choice so
                    //the same choice can be used again
                    var iconChanged = so.WhenValueChanged(proxy => proxy.IconKind,false).ToUnit();
                    var colourChanged = so.WhenValueChanged(proxy => proxy.HighlightHue, false).ToUnit();
                    var ignoreCaseChanged = so.WhenValueChanged(proxy => proxy.IgnoreCase, false).ToUnit();

                    var textAssociationChanged = iconChanged.Merge(colourChanged).Merge(ignoreCaseChanged)
                                .Throttle(TimeSpan.FromMilliseconds(250))
                                .Select(_=> new TextAssociation(so.Text, so.IgnoreCase, so.UseRegex, so.HighlightHue.Swatch, so.IconKind.ToString(), so.HighlightHue.Name, DateTime.Now))
                                .Subscribe(textAssociationCollection.MarkAsChanged);

                    return new CompositeDisposable(anyPropertyHasChanged, textAssociationChanged);
                })
                .AsObservableCache();

            var monitor = MonitorPositionalChanges()
                .Subscribe(metadataCollection.Add);

            //load data onto grid
            var collection = new ObservableCollectionExtended<SearchOptionsProxy>();

            var userOptions = proxyItems.Connect()
                .Sort(SortExpressionComparer<SearchOptionsProxy>.Ascending(proxy => proxy.Position))
                .ObserveOn(schedulerProvider.MainThread)
                //force reset for each new or removed item dues to a bug in the underlying dragablz control which inserts in an incorrect position
                .Bind(collection, new ObservableCollectionAdaptor<SearchOptionsProxy, string>(0))
                .DisposeMany()
                .Subscribe();

            Data = new ReadOnlyObservableCollection<SearchOptionsProxy>(collection);

            //command to add the current search to the tail collection
            var searchInvoker = SearchHints.SearchRequested
                .ObserveOn(schedulerProvider.Background)
                .Subscribe(request =>
                {
                    var meta = searchMetadataFactory.Create(request.Text,
                        request.UseRegEx,
                        metadataCollection.NextIndex(),
                        false);
                    metadataCollection.AddorUpdate(meta);
                });

            _cleanUp = new CompositeDisposable(searchInvoker,
                userOptions,
                searchInvoker,
                monitor,
                SearchHints);
        }
Пример #15
0
        public InterpCurve(IMEPackage _pcc, StructProperty prop)
        {
            pcc = _pcc;

            Curves    = new ObservableCollectionExtended <Curve>();
            Name      = prop.Name;
            curveType = Enums.Parse <CurveType>(prop.StructType);

            float     InVal      = 0f;
            CurveMode InterpMode = CurveMode.CIM_Linear;
            var       points     = prop.Properties.GetProp <ArrayProperty <StructProperty> >("Points");

            switch (curveType)
            {
            case CurveType.InterpCurveQuat:
                throw new NotImplementedException($"InterpCurveQuat has not been implemented yet.");

            case CurveType.InterpCurveFloat:
                float OutVal        = 0f;
                float ArriveTangent = 0f;
                float LeaveTangent  = 0f;
                var   vals          = new LinkedList <CurvePoint>();
                foreach (var point in points)
                {
                    foreach (var p in point.Properties)
                    {
                        switch (p)
                        {
                        case FloatProperty floatProp when floatProp.Name == "InVal":
                            InVal = floatProp.Value;
                            break;

                        case FloatProperty floatProp when floatProp.Name == "OutVal":
                            OutVal = floatProp.Value;
                            break;

                        case FloatProperty floatProp when floatProp.Name == "ArriveTangent":
                            ArriveTangent = floatProp.Value;
                            break;

                        case FloatProperty floatProp when floatProp.Name == "LeaveTangent":
                            LeaveTangent = floatProp.Value;
                            break;

                        case EnumProperty enumProp when enumProp.Name == "InterpMode" && Enum.TryParse(enumProp.Value, out CurveMode enumVal):
                            InterpMode = enumVal;
                            break;
                        }
                    }
                    vals.AddLast(new CurvePoint(InVal, OutVal, ArriveTangent, LeaveTangent, InterpMode));
                }
                Curves.Add(new Curve("X", vals));
                break;

            case CurveType.InterpCurveVector:
                Vector3 OutValVec        = new Vector3(0, 0, 0);
                Vector3 ArriveTangentVec = new Vector3(0, 0, 0);
                Vector3 LeaveTangentVec  = new Vector3(0, 0, 0);
                var     x = new LinkedList <CurvePoint>();
                var     y = new LinkedList <CurvePoint>();
                var     z = new LinkedList <CurvePoint>();
                foreach (var point in points)
                {
                    foreach (var p in point.Properties)
                    {
                        switch (p)
                        {
                        case FloatProperty floatProp when floatProp.Name == "InVal":
                            InVal = floatProp.Value;
                            break;

                        case StructProperty structProp when structProp.Name == "OutVal":
                            OutValVec = CommonStructs.GetVector3(structProp);
                            break;

                        case StructProperty structProp when structProp.Name == "ArriveTangent":
                            ArriveTangentVec = CommonStructs.GetVector3(structProp);
                            break;

                        case StructProperty structProp when structProp.Name == "LeaveTangent":
                            LeaveTangentVec = CommonStructs.GetVector3(structProp);
                            break;

                        case EnumProperty enumProp when enumProp.Name == "InterpMode" && Enum.TryParse(enumProp.Value, out CurveMode enumVal):
                            InterpMode = enumVal;
                            break;
                        }
                    }
                    x.AddLast(new CurvePoint(InVal, OutValVec.X, ArriveTangentVec.X, LeaveTangentVec.X, InterpMode));
                    y.AddLast(new CurvePoint(InVal, OutValVec.Y, ArriveTangentVec.Y, LeaveTangentVec.Y, InterpMode));
                    z.AddLast(new CurvePoint(InVal, OutValVec.Z, ArriveTangentVec.Z, LeaveTangentVec.Z, InterpMode));
                }
                if (Name == "EulerTrack")
                {
                    Curves.Add(new Curve("Roll", x));
                    Curves.Add(new Curve("Pitch", y));
                    Curves.Add(new Curve("Yaw", z));
                }
                else
                {
                    Curves.Add(new Curve("X", x));
                    Curves.Add(new Curve("Y", y));
                    Curves.Add(new Curve("Z", z));
                }
                break;

            case CurveType.InterpCurveVector2D:
                throw new NotImplementedException($"InterpCurveVector2D has not been implemented yet.");

            case CurveType.InterpCurveTwoVectors:
                throw new NotImplementedException($"InterpCurveTwoVectors has not been implemented yet.");

            case CurveType.InterpCurveLinearColor:
                throw new NotImplementedException($"InterpCurveLinearColor has not been implemented yet.");
            }
            foreach (var curve in Curves)
            {
                curve.SharedValueChanged += Curve_SharedValueChanged;
                curve.ListModified       += Curve_ListModified;
            }
        }
Пример #16
0
        public void AutoPersistCollectionDisconnectsOnDispose()
        {
            new TestScheduler().With(sched =>
            {
                var manualSave = new Subject <Unit>();

                var item    = new TestFixture();
                var fixture = new ObservableCollectionExtended <TestFixture> {
                    item
                };

                var timesSaved = 0;
                var disp       = fixture.AutoPersistCollection(x =>
                {
                    timesSaved++;
                    return(Observables.Unit);
                },
                                                               manualSave,
                                                               TimeSpan.FromMilliseconds(100));

                sched.AdvanceByMs(2 * 100);
                Assert.Equal(0, timesSaved);

                // By being added to collection, AutoPersist is enabled for item
                item.IsNotNullString = "Foo";
                sched.AdvanceByMs(2 * 100);
                Assert.Equal(1, timesSaved);

                // Dispose = no save
                disp.Dispose();

                // Removed from collection = no save
                fixture.Clear();
                sched.AdvanceByMs(2 * 100);
                Assert.Equal(1, timesSaved);

                // Item isn't in the collection, it doesn't get persisted anymore
                item.IsNotNullString = "Bar";
                sched.AdvanceByMs(2 * 100);
                Assert.Equal(1, timesSaved);

                // Added back item + dispose = no save
                fixture.Add(item);
                sched.AdvanceByMs(100);  // Compensate for scheduling
                item.IsNotNullString = "Baz";
                sched.AdvanceByMs(2 * 100);
                Assert.Equal(1, timesSaved);

                // Even if we issue a reset, no save
                fixture.SuspendNotifications().Dispose(); // Will trigger a reset.
                sched.AdvanceByMs(100);                   // Compensate for scheduling
                item.IsNotNullString = "Bamf";
                sched.AdvanceByMs(2 * 100);
                Assert.Equal(1, timesSaved);

                // Remove by hand = no save
                fixture.RemoveAt(0);
                item.IsNotNullString = "Blomf";
                sched.AdvanceByMs(2 * 100);
                Assert.Equal(1, timesSaved);
            });
        }
 public ObservableCollectionExtendedToChangeSetFixture()
 {
     _collection = new ObservableCollectionExtended <int>();
     _target     = new ReadOnlyObservableCollection <int>(_collection);
     _results    = _target.ToObservableChangeSet().AsAggregator();
 }
Пример #18
0
        public AddMethodDialogViewModel(IConcurrencyService concurrencyService)
        {
            var methods = new ObservableCollectionExtended <Item>();

            Methods = new ReadOnlyObservableCollection <Item>(methods);

            var whenUserCancels = CommandHelper.CreateTriggerCommand(out var cancelCommand);

            CancelCommand = cancelCommand;
            var whenUserAccepts = CommandHelper.CreateTriggerCommand(out var acceptCommand);

            AcceptCommand = acceptCommand;

            mSelectedMethodHelper = this.WhenAnyValue(x => x.SelectedItem)
                                    .Select(item => item as MethodItem)
                                    .ToProperty(this, nameof(SelectedMethod));
            mSelectedTypeHelper = this.WhenAnyValue(x => x.SelectedItem)
                                  .Select(item => item as TypeItem)
                                  .ToProperty(this, nameof(SelectedType));
            mAcceptCommandTextHelper = this.WhenAnyValue(x => x.SelectedItem)
                                       .Select(item => item is TypeItem ? "See methods" : "Add")
                                       .ToProperty(this, nameof(AcceptCommandText));

            this.WhenActivated((CompositeDisposable disposables) =>
            {
                SearchString = string.Empty;
                SelectedItem = null;
                ChosenType   = null;
                methods.Clear();

                var whenSearchStringChanges = this.WhenAnyValue(x => x.SearchString)
                                              .ObserveOn(concurrencyService.TaskPoolRxScheduler);

                var whenChosenTypeChanges = this.WhenAnyValue(x => x.ChosenType)
                                            .ObserveOn(concurrencyService.TaskPoolRxScheduler);

                whenSearchStringChanges
                .CombineLatest(whenChosenTypeChanges, (searchString, chosenType) => (searchString, chosenType))
                .ObserveOn(concurrencyService.TaskPoolRxScheduler)
                .Select(inputs => MakeScorers(inputs.searchString, inputs.chosenType))
                .Select(scorers =>
                        Model.Modules
                        .ObserveOn(concurrencyService.TaskPoolRxScheduler)
                        .SelectMany(m => m.InstrumentedMethods)
                        .Publish(ms =>
                {
                    var methodItems = ms
                                      .Select(m => m.SourceMethod)
                                      .Distinct()
                                      .Select(m => (method: m, score: scorers.scoreMethod(m)))
                                      .Where(m => m.score.HasValue)
                                      .Select(m => (Item) new MethodItem(m.method, m.score.Value, scorers.scorer));

                    var typeItems = ms
                                    .Select(m => m.SourceMethod.ParentType)
                                    .Distinct()
                                    .Select(t => (type: t, score: scorers.scoreType(t)))
                                    .Where(t => t.score.HasValue)
                                    .Select(t => (Item) new TypeItem(t.type, t.score.Value, scorers.scorer));

                    return(methodItems.Merge(typeItems));
                })
                        .ToObservableChangeSet()
                        .Sort(Utility.Comparer <Item> .ByKey(item => - item.Score)))
                .Select(items =>
                        Observable.Defer(() =>
                {
                    methods.Clear();
                    return(items
                           .ObserveOn(concurrencyService.DispatcherRxScheduler)
                           .Bind(methods));
                }).SubscribeOn(concurrencyService.DispatcherRxScheduler))
                .Switch()
                .Subscribe()
                .DisposeWith(disposables);

                (Func <ISourceMethod, int?> scoreMethod, Func <string, int?> scoreType, IMatchScorer scorer)MakeScorers(string s, TypeItem chosenType)
                {
                    var scorer = MatchScorerFactory.Default.Create(s);

                    if (chosenType != null)
                    {
                        string typeToMatch = chosenType.FullTypeName;
                        if (string.IsNullOrWhiteSpace(s))
                        {
                            return(m => m.ParentType == typeToMatch ? (int?)0 : null, Funcs <string> .DefaultOf <int?>(), scorer);
                        }

                        return(m => m.ParentType == typeToMatch ? GetScoreOrNull(m.Name) : null, Funcs <string> .DefaultOf <int?>(), scorer);
                    }

                    if (string.IsNullOrWhiteSpace(s))
                    {
                        return(Funcs <ISourceMethod> .DefaultOf <int?>(), Funcs <string> .DefaultOf <int?>(), scorer);
                    }

                    return(m => GetScoreOrNull(m.Name), GetScoreOrNull, scorer);

                    int?GetScoreOrNull(string n)
                    {
                        int score = scorer.Score(n);
                        if (score != int.MinValue)
                        {
                            return(score);
                        }

                        return(null);
                    };
                }

                whenUserCancels.Subscribe(_ => Cancel())
                .DisposeWith(disposables);

                Methods.ToObservableChangeSet()
                .ObserveOn(concurrencyService.TaskPoolRxScheduler)
                .Top(1)
                .OnItemAdded(firstItem => SelectedItem = firstItem)
                .Subscribe()
                .DisposeWith(disposables);

                this.WhenAnyValue(x => x.SelectedItem)
                .ObserveOn(concurrencyService.DispatcherRxScheduler)
                .Select(item =>
                {
                    if (item is MethodItem m)
                    {
                        return(whenUserAccepts.Do(_ => Proceed(m.Method)));
                    }

                    if (item is TypeItem t)
                    {
                        return(whenUserAccepts.Do(_ =>
                        {
                            ChosenType = t;
                            SearchString = string.Empty;
                        }));
                    }

                    return(Observable.Empty <Unit>());
                })
                .Switch()
                .Subscribe()
                .DisposeWith(disposables);
            });
        }
		public void SetUp()
		{
			_collection = new ObservableCollectionExtended<Person>();
			_source = new SourceList<Person>();
			_binder = _source.Connect().Bind(_collection).Subscribe();
		}
Пример #20
0
        public async Task <ObservableCollection <PacketViewModel>?> Filter(IList <PacketViewModel> all,
                                                                           string filter,
                                                                           IReadOnlyFilterData?filterData,
                                                                           CancellationToken cancellationToken,
                                                                           IProgress <float> progress)
        {
            int count            = all.Count;
            int threads          = Environment.ProcessorCount;
            int packetsPerThread = count / threads;

            progress.Report(0);

            var filtered = new ObservableCollectionExtended <PacketViewModel>();

            if (string.IsNullOrEmpty(filter))
            {
                using (filtered.SuspendNotifications())
                {
                    // fast hot path
                    if (filterData == null)
                    {
                        filtered.AddRange(all);
                    }
                    else
                    {
                        foreach (var packet in all)
                        {
                            if (AcceptFilterData(packet, filterData))
                            {
                                filtered.Add(packet);
                            }
                        }
                    }
                }
            }
            else
            {
                PacketPlayerLogin?playerLogin = FindPlayerLogin(all);

                Task[] tasks = new Task[threads];
                List <PacketViewModel>[] partialResults = new List <PacketViewModel> [threads];

                for (int j = 0; j < threads; ++j)
                {
                    int CPU = j;
                    tasks[j] = Task.Run(() =>
                    {
                        var evaluator     = new DatabaseExpressionEvaluator(filter, playerLogin?.PlayerGuid ?? new UniversalGuid());
                        var partialResult = new List <PacketViewModel>(packetsPerThread);
                        var upTo          = CPU == threads - 1 ? count : (CPU + 1) * packetsPerThread;

                        for (int index = CPU * packetsPerThread; index < upTo; ++index)
                        {
                            if (filterData == null || AcceptFilterData(all[index], filterData))
                            {
                                if (evaluator.Evaluate(all[index]) is true)
                                {
                                    partialResult.Add(all[index]);
                                }
                            }

                            if (cancellationToken.IsCancellationRequested)
                            {
                                break;
                            }

                            if (CPU == 0)
                            {
                                if (index % 100 == 0)
                                {
                                    progress.Report(1.0f * index / packetsPerThread);
                                }
                            }
                        }

                        partialResults[CPU] = cancellationToken.IsCancellationRequested ? null ! : partialResult;
                    }, cancellationToken);
                }

                await Task.WhenAll(tasks).ConfigureAwait(true);

                progress.Report(1);

                if (cancellationToken.IsCancellationRequested)
                {
                    return(null);
                }

                using (filtered.SuspendNotifications())
                    foreach (var partialResult in partialResults)
                    {
                        filtered.AddRange(partialResult);
                    }
            }
            return(filtered);
        }
Пример #21
0
 public void SetUp()
 {
     _collection = new ObservableCollectionExtended <Person>();
     _source     = new SourceList <Person>();
     _binder     = _source.Connect().Bind(_collection).Subscribe();
 }
        public void MoreCoolSolution()
        {
            var subject = new SourceCache <Widget, int>(w => w.Id);

            var activeObservable   = new ObservableCollectionExtended <WidgetWrapper>();
            var inactiveObservable = new ObservableCollectionExtended <WidgetWrapper>();

            var activeFilter   = new FilterController <WidgetWrapper>(wrapper => wrapper.Wrapped.Active);
            var inactiveFilter = new FilterController <WidgetWrapper>(wrapper => !wrapper.Wrapped.Active);

            //nothing gets removed from here
            var converted = subject
                            .Connect()
                            .Transform(w => new WidgetWrapper(w))
                            .DisposeMany()
                            .AsObservableCache();

            var active = converted.Connect()
                         .Filter(activeFilter)
                         .Bind(activeObservable)
                         .Subscribe();

            var inactive = converted.Connect()
                           .Filter(inactiveFilter)
                           .Bind(inactiveObservable)
                           .Subscribe();


            //var trigger = converted.Connect()
            //                .WhenValueChanged(w=>w.IsDisposed)

            var w1 = new Widget()
            {
                Id = 0, Active = true
            };
            var w2 = new Widget()
            {
                Id = 1, Active = true
            };

            subject.AddOrUpdate(w1);
            subject.AddOrUpdate(w2);
            Assert.AreEqual(2, activeObservable.Count);
            Assert.AreEqual(0, inactiveObservable.Count);
            Assert.IsFalse(activeObservable[0].IsDisposed);
            Assert.IsFalse(activeObservable[1].IsDisposed);

            //This needs to be done twice to trigger the behavior
            w1.Active = !w1.Active;
            activeFilter.Reevaluate();
            inactiveFilter.Reevaluate();

            w1.Active = !w1.Active;
            activeFilter.Reevaluate();
            inactiveFilter.Reevaluate();

            Assert.AreEqual(2, activeObservable.Count);

            Assert.False(activeObservable[0].IsDisposed);
            Assert.False(activeObservable[1].IsDisposed);
        }
Пример #23
0
 public static void SetBindableColumns([NotNull] DependencyObject element, ObservableCollectionExtended <DataGridColumn> value)
 {
     element.SetValue(BindableColumnsProperty, value);
 }
        public void Initialize(ViewRequest viewRequest)
        {
            if (Shell.Role == ServiceUserRole.Editor)
            {
                Shell.AddVMCommand("File", "Save",
                                   "SaveChangesCommand", this)
                .SetHotKey(ModifierKeys.Control, Key.S);

                Shell.AddVMCommand("Edit", "Add operation from existing templates",
                                   "OpenTemplatesListCommand", this);

                Shell.AddVMCommand("Edit", "Add new operation",
                                   "CreateOperConfigCommand", this);
            }

            Schedules = cachedService.Schedules.SpawnCollection();

            if (viewRequest is TaskEditorRequest request)
            {
                mapper.Map(request.Task, this);
                HasSchedule = ScheduleId > 0;

                if (request.TaskOpers != null)
                {
                    bindedOpers.ClearAndAddRange(request.TaskOpers.OrderBy(to => to.Number)
                                                 .Select(to => mapper.Map <DesktopOperation>(to)));
                }

                if (!string.IsNullOrEmpty(request.Task.Parameters))
                {
                    taskParameters.ClearAndAddRange(JsonConvert
                                                    .DeserializeObject <Dictionary <string, object> >(request.Task.Parameters)
                                                    .Select(pair => new TaskParameter
                    {
                        Name  = pair.Key,
                        Value = pair.Value
                    }));
                }
            }

            if (Id == 0)
            {
                HasSchedule = true;
                ScheduleId  = Schedules.First()?.Id;
                Name        = "New task";
            }

            void Changed(object sender, PropertyChangedEventArgs e)
            {
                if (Shell.Role == ServiceUserRole.Viewer || IsDirty || e.PropertyName == "SelectedOperation")
                {
                    return;
                }
                IsDirty = true;
                Title  += '*';
            }

            AllErrors.Connect()
            .Subscribe(_ => IsValid = !AllErrors.Items.Any());

            this.ObservableForProperty(s => s.HasSchedule)
            .Subscribe(hassch =>
                       ScheduleId = hassch.Value ? Schedules.FirstOrDefault()?.Id : null);

            taskParameters.Connect() //todo: real-time updating of duplicates indicators
            .WhenAnyPropertyChanged("Name")
            .Subscribe(_ =>
            {
                foreach (var dim in TaskParameters)
                {
                    dim.IsDuplicate = false;
                }

                var duplicatgroups = TaskParameters
                                     .GroupBy(dim => dim.Name)
                                     .Where(g => g.Count() > 1)
                                     .ToList();

                foreach (var group in duplicatgroups)
                {
                    foreach (var dim in group)
                    {
                        dim.IsDuplicate = true;
                        dim.HasErrors   = true;
                    }
                }

                this.RaisePropertyChanged(nameof(TaskParameters));
            });

            taskParameters.Connect()
            .WhenAnyPropertyChanged("HasErrors")
            .Subscribe(_ =>
            {
                IsValid = !AllErrors.Items.Any() &&
                          !TaskParameters.Any(param => param.HasErrors);
            });

            TaskParameters = new ObservableCollectionExtended <TaskParameter>();

            taskParameters.Connect()
            .Bind(TaskParameters)
            .Skip(1)
            .Subscribe(_ =>
            {
                UpdateParametersList();
                this.RaisePropertyChanged(nameof(TaskParameters));
            });

            ImplementationTypes = implementationTypes.SpawnCollection();

            BindedOpers = new ObservableCollectionExtended <DesktopOperation>();

            bindedOpers.Connect()
            .Bind(BindedOpers)
            .Subscribe();

            bindedOpers.Connect()
            .Subscribe(_ =>
            {
                var packages = bindedOpers.Items.Where(oper => DataImporters.ContainsKey(oper.ImplementationType))
                               .Select(oper =>
                                       (DeserializeOperationConfigByType(oper.ImplementationType, oper.Config) as
                                        IPackagedImporterConfig)
                                       ?.PackageName).Where(name => !string.IsNullOrEmpty(name)).Distinct().ToList();

                incomingPackages.ClearAndAddRange(packages);
            });

            PropertyChanged += Changed;
        } //init vm
        public MarbleDiagramScreenViewModel(IConcurrencyService concurrencyService)
        {
            var itemGroups = new ObservableCollectionExtended <MarbleObservableItemGroup>();

            ObservableItemGroups = new ReadOnlyObservableCollection <MarbleObservableItemGroup>(itemGroups);

            this.WhenActivated(disposables =>
            {
                itemGroups.Clear();

                var instances = ObservableInstances
                                .TakeUntilDisposed(disposables)
                                .Publish();

                var observableItems = instances
                                      .Transform(obs => Observable.Return(new MarbleObservableItem(concurrencyService)
                {
                    ObservableInstance = obs
                })
                                                 .Expand(item => item.ObservableInstance.Inputs.Select(input => new MarbleObservableItem(concurrencyService)
                {
                    ObservableInstance = input, PrimarySink = item
                }))
                                                 .ToObservableChangeSet(obs => obs.ObservableInstance.ObservableId))
                                      .RemoveKey()
                                      .AsObservableList()
                                      .Or();

                var observableItemsGroupedByCall = observableItems
                                                   .Group(item => item.ObservableInstance.Call.InstrumentedCallId)
                                                   .Transform(group =>
                {
                    var firstItem = group.Cache.Items.First();
                    var observableItemsInGroup = new ObservableCollectionExtended <MarbleObservableItem>();
                    group.Cache.Connect()
                    .OnItemAdded(obsItem => obsItem.Activator.Activate().DisposeWith(disposables))
                    .Sort(Utility.Comparer <MarbleObservableItem> .ByKey(x => x.GetOrdering(), EnumerableComparer <long> .LongerBeforeShorter))
                    .SubscribeOn(concurrencyService.TaskPoolRxScheduler)
                    .ObserveOn(concurrencyService.DispatcherRxScheduler)
                    .Bind(observableItemsInGroup)
                    .Subscribe()
                    .DisposeWith(disposables);

                    return(new MarbleObservableItemGroup(firstItem.GetOrdering(), firstItem.ObservableInstance.Call, new ReadOnlyObservableCollection <MarbleObservableItem>(observableItemsInGroup), concurrencyService));
                });

                observableItemsGroupedByCall
                .Sort(Utility.Comparer <MarbleObservableItemGroup> .ByKey(x => x.Ordering, EnumerableComparer <long> .LongerBeforeShorter))
                .SubscribeOn(concurrencyService.TaskPoolRxScheduler)
                .ObserveOn(concurrencyService.DispatcherRxScheduler)
                .Bind(itemGroups)
                .Subscribe()
                .DisposeWith(disposables);

                instances
                .Minimum(obs => obs.Created.Timestamp.Ticks)
                .DistinctUntilChanged()
                .Select(ticks => new DateTime(ticks, DateTimeKind.Utc))
                .SubscribeOn(concurrencyService.TaskPoolRxScheduler)
                .ObserveOn(concurrencyService.DispatcherRxScheduler)
                .ToProperty(this, x => x.StartTime, out mStartTime)
                .DisposeWith(disposables);

                instances.Connect();
            });
        }
 public ObservableCollectionBindCacheSortedFixture()
 {
     _collection = new ObservableCollectionExtended <Person>();
     _source     = new SourceCache <Person, string>(p => p.Name);
     _binder     = _source.Connect().Sort(_comparer, resetThreshold: 25).Bind(_collection).Subscribe();
 }
        public void ExtendedObservableCollection_ConstructorTest3()
        {
            using (var verify = new Verify())
            {
                var weakNotifier = new WeakNotifier();
                var notifier = new Notifier();
                var temp = new[] { notifier, weakNotifier };

                var result = new ObservableCollectionExtended<object>(temp.AsEnumerable());

                ConstructorAssertions(verify, result, weakNotifier, notifier);
            }
        }
Пример #28
0
 public Side(IObservable <bool> belongsToActiveSideObservable, byte houses, byte initialCount, Action played)
 {
     Store  = new Store(belongsToActiveSideObservable);
     Houses = new ObservableCollectionExtended <House>(Enumerable.Range(0, houses)
                                                       .Select(i => new House(belongsToActiveSideObservable, initialCount, played)));
 }
        public void ExtendedObservableCollection_SerializationTest1()
        {
            using (var verify = new Verify())
            {
                var collection = new ObservableCollectionExtended<Foo>();
                collection.Add(new Foo());
                collection.Add(new Foo());
                collection.Add(new Foo());

                var stream = new System.IO.MemoryStream();
                var fooSerializer = new DataContractSerializer(typeof(ObservableCollectionExtended<Foo>));
                fooSerializer.WriteObject(stream, collection);
                stream.Position = 0;
                var newFoo = (ObservableCollectionExtended<Foo>)fooSerializer.ReadObject(stream);

                verify.AreEqual(collection.Count, newFoo.Count, "collection count was off");

            }
        }
Пример #30
0
 public InventoryEntry(GroceryItemType item, IEnumerable <DateTime> expiryTimes)
 {
     ItemType    = item;
     ExpiryDates = new ObservableCollectionExtended <DateTime>(expiryTimes.OrderBy(x => x));
 }
Пример #31
0
        public SearchProxyCollection(ISearchMetadataCollection metadataCollection,
            Guid id,
            Action<SearchMetadata> changeScopeAction,
            ISchedulerProvider schedulerProvider,
            IColourProvider colourProvider,
            IIconProvider iconsProvider,
            ITextAssociationCollection textAssociationCollection,
            IThemeProvider themeProvider)
        {
            var proxyItems = metadataCollection.Metadata.Connect()
                .WhereReasonsAre(ChangeReason.Add, ChangeReason.Remove) //ignore updates because we update from here
                .Transform(meta =>
                {
                    return new SearchOptionsProxy(meta,
                        changeScopeAction,
                        colourProvider,
                        themeProvider,
                        new IconSelector(iconsProvider, schedulerProvider),
                        m => metadataCollection.Remove(m.SearchText),
                        iconsProvider.DefaultIconSelector,
                        id);
                })
                .SubscribeMany(so =>
                {
                    //when a value changes, write the original value back to the metadata collection
                    var anyPropertyHasChanged = so.WhenAnyPropertyChanged()
                        .Select(_ => (SearchMetadata) so)
                        .Subscribe(metadataCollection.AddorUpdate);

                    //when an icon or colour has changed we need to record user choice so
                    //the same choice can be used again
                    var iconChanged = so.WhenValueChanged(proxy => proxy.IconKind, false).ToUnit();
                    var colourChanged = so.WhenValueChanged(proxy => proxy.HighlightHue, false).ToUnit();
                    var ignoreCaseChanged = so.WhenValueChanged(proxy => proxy.CaseSensitive, false).ToUnit();

                    var textAssociationChanged = iconChanged.Merge(colourChanged).Merge(ignoreCaseChanged)
                        .Throttle(TimeSpan.FromMilliseconds(250))
                        .Select(_ => new TextAssociation(so.Text, so.CaseSensitive, so.UseRegex, so.HighlightHue.Swatch,
                            so.IconKind.ToString(), so.HighlightHue.Name, DateTime.UtcNow))
                        .Subscribe(textAssociationCollection.MarkAsChanged);

                    return new CompositeDisposable(anyPropertyHasChanged, textAssociationChanged);
                })
                .AsObservableCache();

            Count = proxyItems.CountChanged.StartWith(0).ForBinding();

            var monitor = MonitorPositionalChanges().Subscribe(metadataCollection.Add);

            //load data onto grid
            var collection = new ObservableCollectionExtended<SearchOptionsProxy>();

            var includedLoader = proxyItems
                .Connect(proxy => !proxy.IsExclusion)
                .Sort(SortExpressionComparer<SearchOptionsProxy>.Ascending(proxy => proxy.Position))
                .ObserveOn(schedulerProvider.MainThread)
                //force reset for each new or removed item dues to a bug in the underlying dragablz control which inserts in an incorrect position
                .Bind(collection, new ObservableCollectionAdaptor<SearchOptionsProxy, string>(0))
                .DisposeMany()
                .Subscribe();

            ReadOnlyObservableCollection<SearchOptionsProxy> excluded;
            var excludedLoader = proxyItems
                .Connect(proxy => proxy.IsExclusion)
                .Sort(SortExpressionComparer<SearchOptionsProxy>.Ascending(proxy => proxy.Text))
                .ObserveOn(schedulerProvider.MainThread)
                //force reset for each new or removed item dues to a bug in the underlying dragablz control which inserts in an incorrect position
                .Bind(out excluded)
                .DisposeMany()
                .Subscribe();

            Excluded = excluded;
            Included = new ReadOnlyObservableCollection<SearchOptionsProxy>(collection);

            _cleanUp = new CompositeDisposable(proxyItems, includedLoader, excludedLoader, monitor);
        }
Пример #32
0
        public void Test3()
        {
            ObservableCollectionExtended <int> collection = new ObservableCollectionExtended <int>(new [] { 1, 2, 3 }.ToList());

            test(collection);
        }
        public SearchProxyCollection(ISearchMetadataCollection metadataCollection,
                                     Guid id,
                                     Action <SearchMetadata> changeScopeAction,
                                     ISchedulerProvider schedulerProvider,
                                     IColourProvider colourProvider,
                                     IIconProvider iconsProvider,
                                     ITextAssociationCollection textAssociationCollection,
                                     IThemeProvider themeProvider)
        {
            var proxyItems = metadataCollection.Metadata.Connect()
                             .WhereReasonsAre(ChangeReason.Add, ChangeReason.Remove) //ignore updates because we update from here
                             .Transform(meta =>
            {
                return(new SearchOptionsProxy(meta,
                                              changeScopeAction,
                                              colourProvider,
                                              themeProvider,
                                              new IconSelector(iconsProvider, schedulerProvider),
                                              m => metadataCollection.Remove(m.SearchText),
                                              iconsProvider.DefaultIconSelector,
                                              id));
            })
                             .SubscribeMany(so =>
            {
                //when a value changes, write the original value back to the metadata collection
                var anyPropertyHasChanged = so.WhenAnyPropertyChanged()
                                            .Select(_ => (SearchMetadata)so)
                                            .Subscribe(metadataCollection.AddorUpdate);

                //when an icon or colour has changed we need to record user choice so
                //the same choice can be used again
                var iconChanged       = so.WhenValueChanged(proxy => proxy.IconKind, false).ToUnit();
                var colourChanged     = so.WhenValueChanged(proxy => proxy.HighlightHue, false).ToUnit();
                var ignoreCaseChanged = so.WhenValueChanged(proxy => proxy.CaseSensitive, false).ToUnit();

                var textAssociationChanged = iconChanged.Merge(colourChanged).Merge(ignoreCaseChanged)
                                             .Throttle(TimeSpan.FromMilliseconds(250))
                                             .Select(_ => new TextAssociation(so.Text, so.CaseSensitive, so.UseRegex, so.HighlightHue.Swatch,
                                                                              so.IconKind.ToString(), so.HighlightHue.Name, DateTime.UtcNow))
                                             .Subscribe(textAssociationCollection.MarkAsChanged);

                return(new CompositeDisposable(anyPropertyHasChanged, textAssociationChanged));
            })
                             .AsObservableCache();

            Count = proxyItems.CountChanged.StartWith(0).ForBinding();

            var monitor = MonitorPositionalChanges().Subscribe(metadataCollection.Add);

            //load data onto grid
            var collection = new ObservableCollectionExtended <SearchOptionsProxy>();

            var includedLoader = proxyItems
                                 .Connect(proxy => !proxy.IsExclusion)
                                 .Sort(SortExpressionComparer <SearchOptionsProxy> .Ascending(proxy => proxy.Position))
                                 .ObserveOn(schedulerProvider.MainThread)
                                 //force reset for each new or removed item dues to a bug in the underlying dragablz control which inserts in an incorrect position
                                 .Bind(collection, new ObservableCollectionAdaptor <SearchOptionsProxy, string>(0))
                                 .DisposeMany()
                                 .Subscribe();

            ReadOnlyObservableCollection <SearchOptionsProxy> excluded;
            var excludedLoader = proxyItems
                                 .Connect(proxy => proxy.IsExclusion)
                                 .Sort(SortExpressionComparer <SearchOptionsProxy> .Ascending(proxy => proxy.Text))
                                 .ObserveOn(schedulerProvider.MainThread)
                                 //force reset for each new or removed item dues to a bug in the underlying dragablz control which inserts in an incorrect position
                                 .Bind(out excluded)
                                 .DisposeMany()
                                 .Subscribe();


            Excluded = excluded;
            Included = new ReadOnlyObservableCollection <SearchOptionsProxy>(collection);

            _cleanUp = new CompositeDisposable(proxyItems, includedLoader, excludedLoader, monitor);
        }
        public void ExtendedReadOnlyObservableCollection_MemoryTest()
        {
            using (var verify = new Verify())
            {

                Func<WeakReference> builder = () =>
                {

                    var source = new ObservableCollectionExtended<int>();
                    var target = new ReadOnlyObservableCollectionExtended<int>(source);

                    var sourceEvents = new Queue<NotifyCollectionChangedEventArgs>();
                    var targetEvents = new Queue<NotifyCollectionChangedEventArgs>();

                    var sourceEvents2 = new Queue<PropertyChangedEventArgs>();
                    var targetEvents2 = new Queue<PropertyChangedEventArgs>();

                    source.CollectionChanged += (s, e) => sourceEvents.Enqueue(e);
                    target.CollectionChanged += (s, e) => targetEvents.Enqueue(e);

                    source.PropertyChanged += (s, e) => sourceEvents2.Enqueue(e);
                    target.PropertyChanged += (s, e) => targetEvents2.Enqueue(e);

                    Memory.CycleGC();

                    source.Add(1);
                    source.Add(2);
                    source.Add(3);

                    verify.AreEqual(3, sourceEvents.Count, "NotifyCollectionChangedEventArgs in source was wrong");
                    verify.AreEqual(3, targetEvents.Count, "NotifyCollectionChangedEventArgs in target was wrong");
                    verify.AreEqual(6, sourceEvents2.Count, "PropertyChangedEventArgs in source was wrong.  There should be 2 per add.");
                    verify.AreEqual(6, targetEvents2.Count, "PropertyChangedEventArgs in target was wrong. There should be 2 per add.");

                    verify.ItemsAreEqual(source, target, "");

                    return new WeakReference(target);
                };

                var wr = builder();

                Memory.CycleGC();

                verify.IsFalse(wr.IsAlive, "wr wasn't GC'd");
            }
        }
Пример #35
0
        public EventListViewModel(IConcurrencyService concurrencyService)
        {
            var eventsCollection = new ObservableCollectionExtended <EventItem>();

            Events = new ReadOnlyObservableCollection <EventItem>(eventsCollection);

            var selectionChangeSubject = new Subject <Func <Selection, Selection> >();

            mSubmitSelectionChange    = selectionChangeSubject.OnNext;
            WhenEventSelectionChanges = selectionChangeSubject
                                        .ObserveOn(concurrencyService.TaskPoolRxScheduler);

            this.WhenActivated((CompositeDisposable disposables) =>
            {
                var whenIncludeInputsChanges =
                    IncludeInputObservables
                    ?.ObserveOn(concurrencyService.TaskPoolRxScheduler)
                    .DistinctUntilChanged()
                    ?? Observable.Return(false);

                var eventsProcessedUntilInvalid =
                    whenIncludeInputsChanges.Publish(whenIncludeInputsChangesPub =>
                                                     whenIncludeInputsChangesPub.SelectMany(includeInputs =>
                                                                                            Observables
                                                                                            .ObserveOn(concurrencyService.TaskPoolRxScheduler)
                                                                                            .Replay(observablesPub =>
                {
                    var observablesExpanded =
                        observablesPub
                        .MergeMany(obs => Observable.Return(obs))
                        .ExpandDistinct(obs => includeInputs ? obs.Inputs : Observable.Empty <IObservableInstance>());

                    var events = observablesExpanded
                                 .SelectMany(obs => Observable.Return(EventItem.FromObservableInstance(obs))
                                             .Concat(obs.Subscriptions.SelectMany(sub => sub.Events.Select(e => EventItem.FromStreamEvent(sub, e)))))
                                 .Merge(ClientEvents?.Select(EventItem.FromClientEvent) ?? Observable.Empty <EventItem>());

                    var eventsProcessed = events
                                          .ToObservableChangeSet(e => e.SequenceId)
                                          .Filter(SequenceIdRange?.Select(CreateFilter) ?? Observable.Return <Func <EventItem, bool> >(_ => true))
                                          .Batch(TimeSpan.FromMilliseconds(100))
                                          .Sort(Utility.Comparer <EventItem> .ByKey(e => e.SequenceId));

                    // Terminate the stream if an observable is removed or the include inputs
                    // flag changes, as in both cases we need to rebuild the output from scratch.
                    return(eventsProcessed
                           .TakeUntil(observablesPub.Where(chg => chg.Removes > 0))
                           .TakeUntil(whenIncludeInputsChangesPub.Where(ii => ii != includeInputs)));
                }))
                                                     )
                    .SubscribeOn(concurrencyService.TaskPoolRxScheduler);

                Observable.Defer(() =>
                {
                    eventsCollection.Clear();

                    return(eventsProcessedUntilInvalid
                           .ObserveOn(concurrencyService.DispatcherRxScheduler)
                           .Bind(eventsCollection, new SortedObservableCollectionAdaptor <EventItem, long>(int.MaxValue)));
                })
                .SubscribeOn(concurrencyService.DispatcherRxScheduler)
                .Repeat()
                .Subscribe()
                .DisposeWith(disposables);
            });

            Func <EventItem, bool> CreateFilter((long start, long end) range)
            {
                return(e => e.SequenceId >= range.start && e.SequenceId <= range.end);
            }
        }
        public void ExtendedReadOnlyObservableCollection_OnItemPropertyChanged()
        {
            using (var verify = new Verify())
            {
                var list = new ObservableCollectionExtended<Notifier>();
                var result = new ReadOnlyObservableCollectionExtended<Notifier>(list);
                var itemPropertyAssert = new ItemPropertyChangedEventTest(verify, result);

                var notifier = new Notifier();
                list.Add(notifier);
                notifier.Name = "Frank";

                itemPropertyAssert.ExpectEvent(notifier, "Name");
            }
        }