Skip to content

Instantly share code, notes, and snippets.

@RolandPheasant
Last active April 14, 2019 15:02
Show Gist options
  • Save RolandPheasant/3a1bd4cd8c2c7d73ebe43118c5ee18c1 to your computer and use it in GitHub Desktop.
Save RolandPheasant/3a1bd4cd8c2c7d73ebe43118c5ee18c1 to your computer and use it in GitHub Desktop.
StackOverflow: MergeManyFix
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using DynamicData.Binding;
using FluentAssertions;
using ReactiveUI;
using Xunit;
namespace DynamicData.ReactiveUI.Tests
{
public class OriginalExample
{
private readonly MainViewModel _mainViewModel;
public OriginalExample()
{
_mainViewModel = new MainViewModel();
_mainViewModel.OpenDocuments.Add(new DocumentViewModel("1"));
_mainViewModel.OpenDocuments.Add(new DocumentViewModel("2"));
_mainViewModel.OpenDocuments.Add(new DocumentViewModel("3"));
_mainViewModel.OpenDocuments.Add(new DocumentViewModel("4"));
}
[Fact]
public void RunFixedVersion()
{
RunTest(true);
}
[Fact]
public void RunBrokenVersion()
{
RunTest(false);
}
private void RunTest(bool useFixedVersion)
{
var sut = CreateSut(useFixedVersion);
sut.OpenDocuments.Count.Should().Be(4);
sut.OpenDocuments.Any(dvm => dvm.Id == "1").Should().BeTrue();
sut.OpenDocuments[0].Close.Execute().Subscribe();
sut.OpenDocuments.Count.Should().Be(3);
sut.OpenDocuments.Any(dvm => dvm.Id == "1").Should().BeFalse();
sut.OpenDocuments[0].Close.Execute().Subscribe();
sut.OpenDocuments.Count.Should().Be(2);
sut.OpenDocuments.Any(dvm => dvm.Id == "2").Should().BeFalse();
}
private MainViewModel CreateSut(bool useFixedVersion)
{
var sut = new MainViewModel(useFixedVersion);
sut.OpenDocuments.Add(new DocumentViewModel("1"));
sut.OpenDocuments.Add(new DocumentViewModel("2"));
sut.OpenDocuments.Add(new DocumentViewModel("3"));
sut.OpenDocuments.Add(new DocumentViewModel("4"));
return sut;
}
public class MainViewModel : ReactiveObject
{
public ObservableCollection<DocumentViewModel> OpenDocuments { get; }
public MainViewModel(bool useFix = true)
{
OpenDocuments = new ObservableCollection<DocumentViewModel>();
//Fixed version
if (useFix)
{
//Fixed
OpenDocuments
.ToObservableChangeSet()
.MergeMany(x => x.Close.Select(_ => x))
.Subscribe(x => OpenDocuments.Remove(x));
}
else
{
//Broken
OpenDocuments
.ToObservableChangeSet()
.AutoRefreshOnObservable(document => document.Close)
.Select(_ => WhenAnyDocumentClosed())
.Switch()
.Subscribe(x => OpenDocuments.Remove(x));
}
}
IObservable<DocumentViewModel> WhenAnyDocumentClosed()
{
return OpenDocuments
.Select(x => x.Close.Select(_ => x))
.Merge();
}
}
public class DocumentViewModel : ReactiveObject
{
public string Id { get; }
public ReactiveCommand<Unit, Unit> Close { get; }
public DocumentViewModel(string id)
{
Id = id;
// Note that we don't actually *subscribe* to Close here or implement
// anything in DocumentViewModel, because Closing is a responsibility
// of the document list.
Close = ReactiveCommand.Create(() => { });
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment