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); } }
public TestFixture() { TestCollection = new ObservableCollectionExtended <int>(); }
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(); }
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); }
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; } }
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(); }
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(); }
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); }
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); }
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); } }
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"); } }
public InventoryEntry(GroceryItemType item, IEnumerable <DateTime> expiryTimes) { ItemType = item; ExpiryDates = new ObservableCollectionExtended <DateTime>(expiryTimes.OrderBy(x => x)); }
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 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"); } }
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"); } }