Skip to content

Instantly share code, notes, and snippets.

@runceel
Created June 19, 2015 05:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save runceel/385d80e7ae4caaf9015f to your computer and use it in GitHub Desktop.
Save runceel/385d80e7ae4caaf9015f to your computer and use it in GitHub Desktop.
using Reactive.Bindings;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace WpfApplication11
{
public class MainWindowViewModel
{
private readonly ObservableCollection<Person> people = new ObservableCollection<Person>();
public ReadOnlyReactiveCollection<PersonViewModel> People { get; private set; }
public ReactiveCommand AddCommand { get; private set; }
private DuplicateManager duplicateManager = new DuplicateManager();
public MainWindowViewModel()
{
this.People = people.ToReadOnlyReactiveCollection(x =>
{
var vm = new PersonViewModel(x);
vm.Disposed += this.VM_Disposed;
this.duplicateManager.Added(vm);
vm.Name.Subscribe(_ => this.NameChanged(vm));
return vm;
});
this.AddCommand = new ReactiveCommand();
this.AddCommand.Subscribe(_ => this.people.Add(new Person { Name = "okazuki" }));
var collectionChanged = this.people
.ToCollectionChanged();
}
private void NameChanged(PersonViewModel vm)
{
this.duplicateManager.Changed(vm);
}
private void VM_Disposed(object sender, EventArgs e)
{
var vm = (PersonViewModel)sender;
this.duplicateManager.Removed(vm);
vm.Disposed -= this.VM_Disposed;
}
}
class DuplicateManager
{
private readonly Dictionary<string, List<PersonViewModel>> map = new Dictionary<string, List<PersonViewModel>>();
private readonly Dictionary<PersonViewModel, string> reverseMap = new Dictionary<PersonViewModel, string>();
public void Added(PersonViewModel vm)
{
this.reverseMap[vm] = vm.Name.Value;
var list = this.GetMapList(vm.Name.Value);
list.Add(vm);
this.ApplyBackgroundColor(list);
}
public void Changed(PersonViewModel vm)
{
this.Removed(vm);
this.Added(vm);
}
public void Removed(PersonViewModel vm)
{
var oldName = this.reverseMap[vm];
var list = this.GetMapList(oldName);
list.Remove(vm);
this.reverseMap.Remove(vm);
this.ApplyBackgroundColor(list);
}
private List<PersonViewModel> GetMapList(string p)
{
if (this.map.ContainsKey(p))
{
return this.map[p];
}
var list = new List<PersonViewModel>();
map[p] = list;
return list;
}
private void ApplyBackgroundColor(List<PersonViewModel> l)
{
var color = l.Count > 1 ? "Red" : "White";
foreach (var item in l) { item.BackgroundColor.Value = color; }
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WpfApplication11
{
public class Person : BindableBase
{
private string name;
public string Name
{
get { return this.name; }
set { this.SetProperty(ref this.name, value); }
}
}
}
using Reactive.Bindings;
using Reactive.Bindings.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Text;
using System.Threading.Tasks;
namespace WpfApplication11
{
public class PersonViewModel : IDisposable
{
private readonly CompositeDisposable disposable = new CompositeDisposable();
public ReactiveProperty<string> Name { get; private set; }
public ReactiveProperty<string> BackgroundColor { get; private set; }
public event EventHandler Disposed;
public PersonViewModel(Person model)
{
this.Name = model
.ToReactivePropertyAsSynchronized(x => x.Name)
.AddTo(this.disposable);
this.BackgroundColor = new ReactiveProperty<string>("White");
}
public void Dispose()
{
if (this.disposable.IsDisposed) { return; }
this.disposable.Dispose();
var h = this.Disposed;
if (h != null) { h(this, EventArgs.Empty); }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment