private void CreateSuggestions(int topSuggestionsCount) { var suggestionLabelsFilter = this.WhenAnyValue(x => x.Labels).Select(_ => Unit.Default) .Merge(Observable.FromEventPattern(Labels, nameof(Labels.CollectionChanged)).Select(_ => Unit.Default)) .Select(_ => SuggestionLabelsFilter()); _sourceLabels .Connect() .Filter(suggestionLabelsFilter) .Sort(SortExpressionComparer <SuggestionLabelViewModel> .Descending(x => x.Count).ThenByAscending(x => x.Label)) .Top(topSuggestionsCount) .Transform(x => x.Label) .ObserveOn(RxApp.MainThreadScheduler) .Bind(_topSuggestions) .Subscribe(); _sourceLabels .Connect() .Filter(suggestionLabelsFilter) .Sort(SortExpressionComparer <SuggestionLabelViewModel> .Descending(x => x.Count).ThenByAscending(x => x.Label)) .Transform(x => x.Label) .ObserveOn(RxApp.MainThreadScheduler) .Bind(_suggestions) .Subscribe(); Func <SuggestionLabelViewModel, bool> SuggestionLabelsFilter() => suggestionLabel => !_labels.Contains(suggestionLabel.Label); }
public ConfirmRecoveryWordsViewModel(NavigationStateViewModel navigationState, List <RecoveryWordViewModel> mnemonicWords, KeyManager keyManager, WalletManager walletManager) : base(navigationState, NavigationTarget.DialogScreen) { _confirmationWordsSourceList = new SourceList <RecoveryWordViewModel>(); var finishCommandCanExecute = _confirmationWordsSourceList .Connect() .ObserveOn(RxApp.MainThreadScheduler) .WhenValueChanged(x => x.IsConfirmed) .Select(x => !_confirmationWordsSourceList.Items.Any(x => !x.IsConfirmed)); NextCommand = ReactiveCommand.Create( () => { walletManager.AddWallet(keyManager); ClearNavigation(NavigationTarget.DialogScreen); }, finishCommandCanExecute); CancelCommand = ReactiveCommand.Create(() => ClearNavigation(NavigationTarget.DialogScreen)); _confirmationWordsSourceList .Connect() .ObserveOn(RxApp.MainThreadScheduler) .OnItemAdded(x => x.Reset()) .Sort(SortExpressionComparer <RecoveryWordViewModel> .Ascending(x => x.Index)) .Bind(out _confirmationWords) .Subscribe(); // Select 4 random words to confirm. _confirmationWordsSourceList.AddRange(mnemonicWords.OrderBy(x => new Random().NextDouble()).Take(4)); }
public AggregationViewModel() { var sourceList = new SourceList<AggregationItem>(); sourceList.AddRange(Enumerable.Range(1, 15).Select(i => new AggregationItem(i))); //Load items to display to user and allow them to include items or not var listLoader = sourceList.Connect() .Sort(SortExpressionComparer<AggregationItem>.Ascending(vm => vm.Number)) .ObserveOnDispatcher() .Bind(out _items) .Subscribe(); // share the connection because we are doing multiple aggregations var aggregatable = sourceList.Connect() .FilterOnProperty(vm => vm.IncludeInTotal, vm => vm.IncludeInTotal) .Publish(); //Do a custom aggregation (ToCollection() produces a readonly collection of underlying data) var sumOfOddNumbers = aggregatable.ToCollection() .Select(collection => collection.Where(i => i.Number%2 == 1).Select(ai => ai.Number).Sum()) .Subscribe(sum => SumOfOddNumbers = sum); _cleanUp = new CompositeDisposable(sourceList, listLoader, aggregatable.Count().Subscribe(count => Count = count), aggregatable.Sum(ai => ai.Number).Subscribe(sum => Sum = sum), aggregatable.Avg(ai => ai.Number).Subscribe(average => Avg = Math.Round(average,2)), aggregatable.Minimum(ai => ai.Number).Subscribe(max => Max = max), aggregatable.Maximum(ai => ai.Number).Subscribe(min => Min = min), aggregatable.StdDev(ai => ai.Number).Subscribe(std => StdDev = Math.Round(std, 2)), sumOfOddNumbers, aggregatable.Connect()); }
public PrivacyControlViewModel(Wallet wallet, TransactionInfo transactionInfo, TransactionBroadcaster broadcaster) { _wallet = wallet; _pocketSource = new SourceList <PocketViewModel>(); _pocketSource.Connect() .Bind(out _pockets) .Subscribe(); var selected = _pocketSource.Connect() .AutoRefresh() .Filter(x => x.IsSelected); _selectedList = selected.AsObservableList(); selected.Sum(x => x.TotalBtc) .Subscribe(x => { if (_privatePocket is { }) { _privatePocket.IsWarningOpen = _privatePocket.IsSelected && _selectedList.Count > 1; } StillNeeded = transactionInfo.Amount.ToDecimal(MoneyUnit.BTC) - x; EnoughSelected = StillNeeded <= 0; });
public ConfirmRecoveryWordsViewModel(IScreen screen, List <RecoveryWordViewModel> mnemonicWords, KeyManager keyManager, WalletManager walletManager) { HostScreen = screen; _confirmationWordsSourceList = new SourceList <RecoveryWordViewModel>(); var finishCommandCanExecute = _confirmationWordsSourceList .Connect() .ObserveOn(RxApp.MainThreadScheduler) .WhenValueChanged(x => x.IsConfirmed) .Select(x => !_confirmationWordsSourceList.Items.Any(x => !x.IsConfirmed)); FinishCommand = ReactiveCommand.Create( () => { walletManager.AddWallet(keyManager); screen.Router.NavigationStack.Clear(); }, finishCommandCanExecute); _confirmationWordsSourceList .Connect() .ObserveOn(RxApp.MainThreadScheduler) .OnItemAdded(x => x.Reset()) .Sort(SortExpressionComparer <RecoveryWordViewModel> .Ascending(x => x.Index)) .Bind(out _confirmationWords) .Subscribe(); SelectRandomConfirmationWords(mnemonicWords); }
public ConfirmRecoveryWordsViewModel(List <RecoveryWordViewModel> mnemonicWords, KeyManager keyManager, WalletManager walletManager) { var confirmationWordsSourceList = new SourceList <RecoveryWordViewModel>(); var finishCommandCanExecute = confirmationWordsSourceList .Connect() .ObserveOn(RxApp.MainThreadScheduler) .WhenValueChanged(x => x.IsConfirmed) .Select(_ => confirmationWordsSourceList.Items.All(x => x.IsConfirmed)); NextCommand = ReactiveCommand.Create( () => { walletManager.AddWallet(keyManager); Navigate().To(new AddedWalletPageViewModel(keyManager.WalletName, WalletType.Normal)); }, finishCommandCanExecute); CancelCommand = ReactiveCommand.Create(() => Navigate().Clear()); confirmationWordsSourceList .Connect() .ObserveOn(RxApp.MainThreadScheduler) .OnItemAdded(x => x.Reset()) .Sort(SortExpressionComparer <RecoveryWordViewModel> .Ascending(x => x.Index)) .Bind(out _confirmationWords) .Subscribe(); // Select 4 random words to confirm. confirmationWordsSourceList.AddRange(mnemonicWords.OrderBy(_ => new Random().NextDouble()).Take(4)); }
public AggregationViewModel() { var sourceList = new SourceList <AggregationItem>(); sourceList.AddRange(Enumerable.Range(1, 15).Select(i => new AggregationItem(i))); //Load items to display to user and allow them to include items or not var listLoader = sourceList.Connect() .Sort(SortExpressionComparer <AggregationItem> .Ascending(vm => vm.Number)) .ObserveOnDispatcher() .Bind(out _items) .Subscribe(); // share the connection because we are doing multiple aggregations var aggregatable = sourceList.Connect() .FilterOnProperty(vm => vm.IncludeInTotal, vm => vm.IncludeInTotal) .Publish(); //Do a custom aggregation (ToCollection() produces a readonly collection of underlying data) var sumOfOddNumbers = aggregatable.ToCollection() .Select(collection => collection.Where(i => i.Number % 2 == 1).Select(ai => ai.Number).Sum()) .Subscribe(sum => SumOfOddNumbers = sum); _cleanUp = new CompositeDisposable(sourceList, listLoader, aggregatable.Count().Subscribe(count => Count = count), aggregatable.Sum(ai => ai.Number).Subscribe(sum => Sum = sum), aggregatable.Avg(ai => ai.Number).Subscribe(average => Avg = Math.Round(average, 2)), aggregatable.Minimum(ai => ai.Number).Subscribe(max => Max = max), aggregatable.Maximum(ai => ai.Number).Subscribe(min => Min = min), aggregatable.StdDev(ai => ai.Number).Subscribe(std => StdDev = Math.Round(std, 2)), sumOfOddNumbers, aggregatable.Connect()); }
public ConfirmRecoveryWordsViewModel(List <RecoveryWordViewModel> mnemonicWords, KeyManager keyManager) { var confirmationWordsSourceList = new SourceList <RecoveryWordViewModel>(); _isSkipEnable = Services.WalletManager.Network != Network.Main || System.Diagnostics.Debugger.IsAttached; var nextCommandCanExecute = confirmationWordsSourceList .Connect() .ObserveOn(RxApp.MainThreadScheduler) .WhenValueChanged(x => x.IsConfirmed) .Select(_ => confirmationWordsSourceList.Items.All(x => x.IsConfirmed)); EnableBack = true; NextCommand = ReactiveCommand.Create(() => OnNext(keyManager), nextCommandCanExecute); if (_isSkipEnable) { SkipCommand = ReactiveCommand.Create(() => NextCommand.Execute(null)); } CancelCommand = ReactiveCommand.Create(OnCancel); confirmationWordsSourceList .Connect() .ObserveOn(RxApp.MainThreadScheduler) .OnItemAdded(x => x.Reset()) .Sort(SortExpressionComparer <RecoveryWordViewModel> .Ascending(x => x.Index)) .Bind(out _confirmationWords) .Subscribe(); // Select random words to confirm. confirmationWordsSourceList.AddRange(mnemonicWords.OrderBy(_ => new Random().NextDouble()).Take(3)); }
public void RegisterCategory(string title, int order) { if (!_categories.ContainsKey(title)) { var category = new SearchCategory(title, order); _categories.Add(title, category); var sourceList = new SourceList <SearchItemViewModel>(); _categorySources.Add(category, sourceList); if (_sourceObservable is null) { _sourceObservable = sourceList.Connect(); } else { _sourceObservable = _sourceObservable.Merge(sourceList.Connect()); } return; } throw new Exception("Category already exists."); }
public PrivacyControlViewModel(Wallet wallet, TransactionInfo transactionInfo, TransactionBroadcaster broadcaster) { _wallet = wallet; _pocketSource = new SourceList <PocketViewModel>(); _pocketSource.Connect() .Bind(out _pockets) .Subscribe(); var selected = _pocketSource.Connect() .AutoRefresh() .Filter(x => x.IsSelected); var selectedList = selected.AsObservableList(); selected.Sum(x => x.TotalBtc) .Subscribe(x => { StillNeeded = transactionInfo.Amount.ToDecimal(MoneyUnit.BTC) - x; EnoughSelected = StillNeeded <= 0; }); StillNeeded = transactionInfo.Amount.ToDecimal(MoneyUnit.BTC); EnableCancel = true; EnableBack = true; NextCommand = ReactiveCommand.CreateFromTask( async() => await OnNext(wallet, transactionInfo, broadcaster, selectedList), this.WhenAnyValue(x => x.EnoughSelected)); EnableAutoBusyOn(NextCommand); }
public FriendConversationViewModel(Tox tox, uint friendNumber) { var messages = new SourceList <MessageViewModel>(); messages.Connect() .AutoRefresh(x => x.Read) .Filter(x => !x.Read) .AsObservableList() .CountChanged .ToPropertyEx(this, x => x.UnreadCount); this.SendMessage = ReactiveCommand.Create <string>(msg => { if (!string.IsNullOrWhiteSpace(msg)) { _ = tox.SendMessage(friendNumber, msg, ToxMessageType.Message, out _); messages.Add(new MessageViewModel("Me", msg, DateTime.Now.Ticks)); } }); ReadOnlyObservableCollection <MessageViewModel> msgs; messages.Connect() .Bind(out msgs) .Subscribe(); this.Messages = msgs; this.SendTypedMessage = ReactiveCommand.Create(() => { var msg = this.InputMessage; this.InputMessage = string.Empty; return(msg); }, this.WhenAnyValue(x => x.InputMessage, (string s) => !string.IsNullOrWhiteSpace(s))); this.WhenAnyValue(x => x.InputMessage) .Select(msg => !string.IsNullOrWhiteSpace(msg)) .Where(x => x) .Do(x => tox.SetTypingStatus(friendNumber, true, out _)) .Throttle(TimeSpan.FromMilliseconds(500)) .Subscribe(x => tox.SetTypingStatus(friendNumber, false, out _)); tox.Events().Friends .Message .Where(x => x.FriendNumber == friendNumber && x.MessageType == ToxMessageType.Message) .Select(x => x.Message) .Subscribe(msg => messages.Add(new MessageViewModel(tox.GetFriendName(friendNumber, out _), msg, DateTime.Now.Ticks))); this.WhenAnyObservable(x => x.SendTypedMessage) .InvokeCommand(this, x => x.SendMessage); }
public PassthroughTestVM(GroupTestVM group, PassthroughVM p) { Group = group; Settings = p; _Name = this.WhenAnyValue(x => x.Settings.Path.TargetPath) .Select(path => { try { return(Path.GetFileName(path)); } catch (Exception) { return(path); } }) .ToGuiProperty(this, nameof(Name), string.Empty); Tests.Connect() .Bind(out _testsDisplay) .Subscribe() .DisposeWith(this); SelectCommand = ReactiveCommand.Create(() => { Group.Parent.SelectedPassthrough = this; }); _IsSelected = Group.Parent.WhenAnyValue(x => x.SelectedPassthrough) .Select(x => x == this) .ToGuiProperty(this, nameof(IsSelected)); _State = Tests.Connect() .AutoRefresh(x => x.State) .Transform(p => p.State, transformOnRefresh: true) .QueryWhenChanged(states => { bool notComplete = false; foreach (var state in states) { if (state == TestState.Error) { return(TestState.Error); } if (state != TestState.Complete) { notComplete = true; } } return(notComplete ? TestState.Running : TestState.Complete); }) .ToGuiProperty(this, nameof(State)); }
public void MultipleSubscribersWithOneThrowing() { var firstSubscriberCallCount = 0; var secondSubscriberCallCount = 0; var s = new SourceList <int>(); s.Connect().Subscribe(i => firstSubscriberCallCount++); s.Connect().Subscribe(i => { throw new NotImplementedException(); }); s.Connect().Subscribe(i => secondSubscriberCallCount++); s.Edit(u => u.Add(1)); Assert.That(firstSubscriberCallCount, Is.EqualTo(1)); Assert.That(secondSubscriberCallCount, Is.EqualTo(1)); }
public void Test() { var a0 = new Item("A0"); var i1 = new Item("I1"); var i2 = new Item("I2"); var i3 = new Item("I3"); var obsList = new SourceList <Item>(); obsList.AddRange(new[] { a0, i1, i2, i3 }); var obsListDerived = obsList.Connect() .AutoRefresh(x => x.Name) .Filter(x => x.Name.Contains("I")) .AsObservableList(); obsListDerived.Count.Should().Be(3); obsListDerived.Items.Should().BeEquivalentTo(new[] { i1, i2, i3 }); i1.Name = "X2"; obsListDerived.Count.Should().Be(2); obsListDerived.Items.Should().BeEquivalentTo(new[] { i2, i3 }); a0.Name = "I0"; obsListDerived.Count.Should().Be(3); obsListDerived.Items.Should().BeEquivalentTo(new[] { a0, i2, i3 }); }
public void AutoRefreshBatched() { var scheduler = new TestScheduler(); var items = Enumerable.Range(1, 100) .Select(i => new Person("Person" + i, 1)) .ToArray(); //result should only be true when all items are set to true using (var list = new SourceList <Person>()) using (var results = list.Connect().AutoRefresh(p => p.Age, TimeSpan.FromSeconds(1), scheduler: scheduler).AsAggregator()) { list.AddRange(items); results.Data.Count.Should().Be(100); results.Messages.Count.Should().Be(1); //update 50 records items.Skip(50) .ForEach(p => p.Age = p.Age + 1); scheduler.AdvanceBy(TimeSpan.FromSeconds(1).Ticks); //should be another message with 50 refreshes results.Messages.Count.Should().Be(2); results.Messages[1].Refreshes.Should().Be(50); } }
public void AutoRefreshSelected() { //test added as v6 broke unit test in DynamicData.Snippets var initialItems = Enumerable.Range(1, 10) .Select(i => new SelectableItem(i)) .ToArray(); //result should only be true when all items are set to true using (var sourceList = new SourceList <SelectableItem>()) using (var sut = sourceList.Connect().AutoRefresh().Filter(si => si.IsSelected).AsObservableList()) { sourceList.AddRange(initialItems); sut.Count.Should().Be(0); initialItems[0].IsSelected = true; sut.Count.Should().Be(1); initialItems[1].IsSelected = true; sut.Count.Should().Be(2); //remove the selected items sourceList.RemoveRange(0, 2); sut.Count.Should().Be(0); } }
public void AutoRefreshDistinct() { var items = Enumerable.Range(1, 100) .Select(i => new Person("Person" + i, i)) .ToArray(); //result should only be true when all items are set to true using (var list = new SourceList <Person>()) using (var results = list.Connect() .AutoRefresh(p => p.Age) .DistinctValues(p => p.Age / 10) .AsAggregator()) { list.AddRange(items); results.Data.Count.Should().Be(11); results.Messages.Count.Should().Be(1); //update an item which did not match the filter and does so after change items[50].Age = 500; results.Data.Count.Should().Be(12); results.Messages.Last().First().Reason.Should().Be(ListChangeReason.Add); results.Messages.Last().First().Item.Current.Should().Be(50); } }
public void AutoRefreshTransform() { var items = Enumerable.Range(1, 100) .Select(i => new Person("Person" + i, i)) .ToArray(); //result should only be true when all items are set to true using (var list = new SourceList <Person>()) using (var results = list.Connect() .AutoRefresh(p => p.Age) .Transform((p, idx) => new TransformedPerson(p, idx)) .AsAggregator()) { list.AddRange(items); results.Data.Count.Should().Be(100); results.Messages.Count.Should().Be(1); //update an item which did not match the filter and does so after change items[0].Age = 60; results.Messages.Count.Should().Be(2); results.Messages.Last().Refreshes.Should().Be(1); results.Messages.Last().First().Item.Reason.Should().Be(ListChangeReason.Refresh); results.Messages.Last().First().Item.Current.Index.Should().Be(0); items[60].Age = 160; results.Messages.Count.Should().Be(3); results.Messages.Last().Refreshes.Should().Be(1); results.Messages.Last().First().Item.Reason.Should().Be(ListChangeReason.Refresh); results.Messages.Last().First().Item.Current.Index.Should().Be(60); } }
public void AutoRefreshGroup() { var items = Enumerable.Range(1, 100) .Select(i => new Person("Person" + i, i)) .ToArray(); //result should only be true when all items are set to true using (var list = new SourceList <Person>()) using (var results = list.Connect() .AutoRefresh(p => p.Age) .GroupOn(p => p.Age % 10) .AsAggregator()) { void CheckContent() { foreach (var grouping in items.GroupBy(p => p.Age % 10)) { var childGroup = results.Data.Items.Single(g => g.GroupKey == grouping.Key); var expected = grouping.OrderBy(p => p.Name); var actual = childGroup.List.Items.OrderBy(p => p.Name); actual.ShouldAllBeEquivalentTo(expected); } } list.AddRange(items); results.Data.Count.Should().Be(10); results.Messages.Count.Should().Be(1); CheckContent(); //move person from group 1 to 2 items[0].Age = items[0].Age + 1; CheckContent(); //change the value and move to a grouping which does not yet exist items[1].Age = -1; results.Data.Count.Should().Be(11); results.Data.Items.Last().GroupKey.Should().Be(-1); results.Data.Items.Last().List.Count.Should().Be(1); results.Data.Items.First().List.Count.Should().Be(9); CheckContent(); //put the value back where it was and check the group was removed items[1].Age = 1; results.Data.Count.Should().Be(10); CheckContent(); var groupOf3 = results.Data.Items.ElementAt(2); IChangeSet <Person> changes = null; groupOf3.List.Connect().Subscribe(c => changes = c); //refresh an item which makes it belong to the same group - should then propagate a refresh items[2].Age = 13; changes.Should().NotBeNull(); changes.Count.Should().Be(1); changes.First().Reason.Should().Be(ListChangeReason.Replace); changes.First().Item.Current.Should().BeSameAs(items[2]); } }
public void ListPerformance(int n) { var list = new SourceList<int>(); int calculated = 0; var sw = Stopwatch.StartNew(); var summation = list.Connect() .Sum(i => i) .Subscribe(result => calculated = result); //1. this is very slow if there are loads of updates (each updates causes a new summation) for (int i = 1; i < n; i++) list.Add(i); //2. very fast doing this (whole range is 1 update and 1 calculation): //list.AddRange(Enumerable.Range(0, n)); sw.Stop(); summation.Dispose(); list.Dispose(); Console.WriteLine("Total items: {0}. Value = {1}", n, calculated); Console.WriteLine("List: {0} updates took {1} ms {2:F3} ms each. {3}", n, sw.ElapsedMilliseconds, sw.Elapsed.TotalMilliseconds / n, DateTime.Now.ToShortDateString()); }
public ViewModel() { // allow bound property updates to happen on the UI thread uiFactory = new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext()); studyAreas = new List <StudyArea>(); PickUnitFromStudyArea = ReactiveCommand.Create <UnitInStudyArea>(unit => PickUnit(unit)); PickUnitFromStudyPlan = ReactiveCommand.Create <UnitInPlan>(unit => PickUnit(unit)); DropInflight = ReactiveCommand.Create(() => DropInFlight()); ScheduleUnit = ReactiveCommand.Create <Semester>(semester => Schedule(semester)); ApplyWizard = ReactiveCommand.CreateFromTask <bool>(Wizard); CancelWizard = ReactiveCommand.Create(() => cancelWizard.Cancel()); SwitchToEN01 = ReactiveCommand.Create(() => { plan.Clear(); studyAreas = LoadCourse(CourseData.Properties.Resources.EN01); }); SwitchToIN01 = ReactiveCommand.Create(() => { plan.Clear(); studyAreas = LoadCourse(CourseData.Properties.Resources.IN01); }); plan.Connect().ToProperty(this, vm => vm.planChange, out _planChange); // Update study area (unit colour coding) when plan or course changes this.WhenAnyValue(vm => vm.planChange, vm => vm.studyAreas) .Select(change => enrollable(plan.Items, studyAreas)) .ToProperty(this, vm => vm.enrollableStudyAreas, out _enrollableStudyAreas); // Update study plan (by semester) when unit picked up or study plan changes this.WhenAnyValue(vm => vm.inFlightUnitCode, vm => vm.planChange) .Select(pair => projectPlan()) .ToProperty(this, vm => vm.semesters, out _semesters); }
internal LogViewerViewModel(UavcanInstance uavcan, TableFilterSetViewModel filter) { _serializer = uavcan.Serializer; ResolveTypes(uavcan.TypeResolver); var messageReceived = Observable.FromEventPattern <EventHandler <TransferReceivedArgs>, TransferReceivedArgs>( handler => uavcan.MessageReceived += handler, handler => uavcan.MessageReceived -= handler); var logItemsFiller = messageReceived .Select(x => GetLogMessage(x)) .Where(x => x != null) .Subscribe(m => _logItemsSource.Add(m)); var filterObservable = filter.WhenValueChanged(t => t.Filter) .Select(BuildFilter); var sourceBuilder = _logItemsSource .Connect() .Filter(filterObservable) .ObserveOn(RxApp.MainThreadScheduler) .Bind(out _logItems) .Subscribe(); AddFilter = ReactiveCommand.Create(() => filter.AddFilter()); _cleanUp = new CompositeDisposable(logItemsFiller, sourceBuilder, filter); }
protected virtual void BuildAndSetObservable() { if (DisposableItems.Count > 0) { return; } var personComparer = Comparer <Person> .Create((x, y) => { return(x.ToString().CompareTo(y.ToString())); }); ReadOnlyObservableCollection <GroupedData> observableCollection; DisposableItems.Add(_itemsSource .Connect() .Sort(personComparer) .Distinct() .GroupOn(x => x.GroupName) .Transform(CreatePersonGroup) .ObserveOn(SynchronizationContext.Current) .Bind(out observableCollection) .DisposeMany() .Subscribe()); Items = observableCollection; }
public LogCollector() { EventsList.Connect() .ObserveOn(RxApp.MainThreadScheduler) .Bind(out eventsBinding) .Subscribe(); }
public void ListPerformance(int n) { var list = new SourceList <int>(); double runningSum = 0; var sw = Stopwatch.StartNew(); var summation = list.Connect() .Minimum(i => i) .Subscribe(result => runningSum = result); //1. this is very slow if there are loads of updates (each updates causes a new summation) for (int i = 0; i < n; i++) { list.Add(i); } //2. very fast doing this (whole range is 1 update and 1 calculation): //list.AddRange(Enumerable.Range(0, n)); sw.Stop(); summation.Dispose(); list.Dispose(); Console.WriteLine("Total items: {0}. Sum = {1}", n, runningSum); Console.WriteLine("List: {0} updates took {1} ms {2:F3} ms each. {3}", n, sw.ElapsedMilliseconds, sw.Elapsed.TotalMilliseconds / n, DateTime.Now.ToShortDateString()); }
public BoxViewModel(IMonik monik, IMapper mapper) { this.mon = monik; this.mapper = mapper; Columns = new SourceList <ColumnViewModel>(); Rows = new SourceList <RowViewModel>(); Boards = new SourceList <BoardViewModel>(); Cards = new SourceList <CardViewModel>(); Cards .Connect() .AutoRefresh() .Subscribe(x => TotalTickets = Cards.Count); Boards .Connect() .AutoRefresh() .Subscribe(bvm => { var lst = Boards.Items.Select(x => x.Name).ToList(); var str = string.Join(",", lst); BoardList = str; }); }
public EndpointsViewModel() { sourceEndpoints = new SourceList<Endpoint>(); var filter = Observable.Return("") .Concat(this.ChangedProperty<string>(nameof(Search)).Select(pc => pc.After)) //.Throttle(TimeSpan.FromMilliseconds(500)) .Select(BuildFilter); sourceEndpoints.Connect() .Filter(filter) .Sort(SortExpressionComparer<Endpoint>.Ascending(e => e.Name)) .ObserveOnUI() .Bind(out endpoints) .Subscribe(); ServiceControl.Instance.Endpoints() .SubscribeOnBackground() .Subscribe(es => { sourceEndpoints.Edit(inner => { inner.Clear(); inner.AddRange(es.DeserializeCollection<Endpoint>()); }); }); }
public void MakeSelectMagicWorkWithObservable() { var initialItem = new IntHolder() { Value = 1, Description = "Initial Description" }; var sourceList = new SourceList <IntHolder>(); sourceList.Add(initialItem); var descriptionStream = sourceList .Connect() .AutoRefresh(intHolder => intHolder.Description) .Transform(intHolder => intHolder.Description, true) .Do(x => { }) // <--- Add break point here to check the overload fixes it .Bind(out ReadOnlyObservableCollection <string> resultCollection); using (descriptionStream.Subscribe()) { var newDescription = "New Description"; initialItem.Description = newDescription; newDescription.Should().Be(resultCollection[0]); //Assert.AreEqual(newDescription, resultCollection[0]); } }
public PullRequestViewModel() { _cacheService = Locator.Current.GetService <ICacheService>(); _pullRequestData = new SourceList <LocalPullRequest>(); ItemTreshold = -1; OpenCount = "0 opened"; CloseCount = "0 closed"; _pullRequestData.Connect() .Sort(SortExpressionComparer <LocalPullRequest> .Descending(x => x.Date)) .ObserveOn(RxApp.MainThreadScheduler) .Do(x => Count()) .Bind(out _pullRequests) .DisposeMany().Subscribe(); ConfigureAddCommand(); ConfigureLoadCommand(); ConfigureLoadCacheCommand(); this.WhenAnyValue(x => x.Repository) .Where(x => x != null) .Select(x => Unit.Default) .InvokeCommand(LoadCacheCommand); }
public HistoryViewModel(WalletViewModel walletViewModel, IObservable <Unit> updateTrigger) { _walletViewModel = walletViewModel; _updateTrigger = updateTrigger; _transactionSourceList = new SourceList <HistoryItemViewModelBase>(); _transactions = new ObservableCollectionExtended <HistoryItemViewModelBase>(); _unfilteredTransactions = new ObservableCollectionExtended <HistoryItemViewModelBase>(); this.WhenAnyValue(x => x.UnfilteredTransactions.Count) .Subscribe(x => IsTransactionHistoryEmpty = x <= 0); _transactionSourceList .Connect() .ObserveOn(RxApp.MainThreadScheduler) .Sort(SortExpressionComparer <HistoryItemViewModelBase> .Ascending(x => x.IsConfirmed) .ThenByDescending(x => x.OrderIndex)) .Bind(_unfilteredTransactions) .Bind(_transactions) .Subscribe(); // [Column] [View] [Header] [Width] [MinWidth] [MaxWidth] [CanUserSort] // Indicators IndicatorsColumnView - Auto 80 - true // Date DateColumnView Date / Time Auto 150 - true // Labels LabelsColumnView Labels * 75 - true // Incoming IncomingColumnView Incoming (BTC) Auto 145 210 true // Outgoing OutgoingColumnView Outgoing (BTC) Auto 145 210 true // Balance BalanceColumnView Balance (BTC) Auto 145 210 true // NOTE: When changing column width or min width please also change HistoryPlaceholderPanel column widths. Source = new HierarchicalTreeDataGridSource <HistoryItemViewModelBase>(_transactions) { Columns = { // Indicators new HierarchicalExpanderColumn <HistoryItemViewModelBase>( new TemplateColumn <HistoryItemViewModelBase>( null, new FuncDataTemplate <HistoryItemViewModelBase>((node,ns) => new IndicatorsColumnView(), true), options: new ColumnOptions <HistoryItemViewModelBase> { CanUserResizeColumn = false, CanUserSortColumn = true, CompareAscending = HistoryItemViewModelBase.SortAscending(x => x.IsCoinJoin), CompareDescending = HistoryItemViewModelBase.SortDescending(x => x.IsCoinJoin), MinWidth = new GridLength(80, GridUnitType.Pixel) }, width: new GridLength(0, GridUnitType.Auto)), x => x.Children, x => { if (x is CoinJoinsHistoryItemViewModel coinJoinsHistoryItemViewModel && coinJoinsHistoryItemViewModel.CoinJoinTransactions.Count > 1) { return(true); } return(false); },
public void BufferInitial() { var scheduler = new TestScheduler(); using (var cache = new SourceList <Person>()) using (var aggregator = cache.Connect().BufferInitial(TimeSpan.FromSeconds(1), scheduler).AsAggregator()) { foreach (var item in People) { cache.Add(item); } aggregator.Data.Count.Should().Be(0); aggregator.Messages.Count.Should().Be(0); scheduler.Start(); aggregator.Data.Count.Should().Be(10_000); aggregator.Messages.Count.Should().Be(1); cache.Add(new Person("_New", 1)); aggregator.Data.Count.Should().Be(10_001); aggregator.Messages.Count.Should().Be(2); } }
public void StressIt() { var list = new SourceList <ClassA>(); var items = Enumerable.Range(1, 10000) .Select(i => new ClassA { Name = i.ToString(), Child = new ClassB { Age = i } }) .ToArray(); list.AddRange(items); var sw = new Stopwatch(); // var factory = var myObservable = list.Connect() .Do(_ => sw.Start()) .WhenPropertyChanged(a => a.Child.Age, false) .Do(_ => sw.Stop()) .Subscribe(); items[1].Child.Age = -1; Console.WriteLine($"{sw.ElapsedMilliseconds}"); }
private void DataReactive(StreamingContext context) { _persons.Connect().WhenPropertyChanged(p => p.relation.value).Subscribe(x => { this.relation.SetBuffer(x.Sender.fullName, x.Value); }); }
public void SkipInitialDoesNotReturnTheFirstBatchOfData() { bool updateReceived = false; var cache = new SourceList<Person>(); var deferStream = cache.Connect().SkipInitial() .Subscribe(changes => updateReceived = true); Assert.IsFalse(updateReceived, "No update should be received"); cache.Add(new Person("P1", 1)); Assert.IsFalse(updateReceived, "No update should be received for initial batch of changes"); cache.Add(new Person("P2", 2)); Assert.IsTrue(updateReceived, "Replace should be received"); deferStream.Dispose(); }
public void MergeManyShouldWork() { var a = new SourceList<int>(); var b = new SourceList<int>(); var c = new SourceList<int>(); var parent = new SourceList<SourceList<int>>(); parent.Add(a); parent.Add(b); parent.Add(c); var d = parent.Connect() .MergeMany(e => e.Connect().RemoveIndex()) .AsObservableList(); Assert.AreEqual(d.Count,0); a.Add(1); Assert.AreEqual(d.Count, 1); a.Add(2); Assert.AreEqual(d.Count, 2); b.Add(3); Assert.AreEqual(d.Count, 3); b.Add(5); Assert.AreEqual(d.Count, 4); CollectionAssert.AreEquivalent(d.Items, new[] { 1, 2, 3, 5 }); b.Clear(); // Fails below Assert.AreEqual(d.Count,2); CollectionAssert.AreEquivalent(d.Items, new[] { 1, 2}); }
public void DeferUntilLoadedDoesNothingUntilDataHasBeenReceived() { bool updateReceived = false; IChangeSet<Person> result = null; var cache = new SourceList<Person>(); var deferStream = cache.Connect().DeferUntilLoaded() .Subscribe(changes => { updateReceived = true; result = changes; }); Assert.IsFalse(updateReceived,"No update should be received"); cache.Add(new Person("Test",1)); Assert.IsTrue(updateReceived,"Replace should be received"); Assert.AreEqual(1,result.Adds); Assert.AreEqual(new Person("Test",1), result.First().Item.Current); deferStream.Dispose(); }
public void SetUp() { _collection = new ObservableCollectionExtended<Person>(); _source = new SourceList<Person>(); _binder = _source.Connect().Bind(_collection).Subscribe(); }