Skip to content

Instantly share code, notes, and snippets.

@patroza
Created November 3, 2012 16:07
Show Gist options
  • Save patroza/4007760 to your computer and use it in GitHub Desktop.
Save patroza/4007760 to your computer and use it in GitHub Desktop.
ReactiveUI ReactiveCollection AddRange/ItemsAdded repro
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel Orientation="Horizontal">
<StackPanel Margin="5">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Original Count" />
<TextBlock Margin="5,0,0,0" Text="{Binding Col.Count}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Manual Count" />
<TextBlock Margin="5,0,0,0" Text="{Binding ManualCount}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="ListBox Original Count" />
<TextBlock Margin="5,0,0,0" Text="{Binding Items.Count, ElementName=LB}" />
</StackPanel>
<TextBlock Text="Original List" />
<ListBox Name="LB" ItemsSource="{Binding Col}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Id}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
<StackPanel Margin="5">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Derived Count" />
<TextBlock Margin="5,0,0,0" Text="{Binding DerivedCol.Count}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Manual Derived Count" />
<TextBlock Margin="5,0,0,0" Text="{Binding ManualDerivedCount}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="ListBox Derived Count" />
<TextBlock Margin="5,0,0,0" Text="{Binding Items.Count, ElementName=DerivedLB}" />
</StackPanel>
<TextBlock Text="Derived List" />
<ListBox Name="DerivedLB" ItemsSource="{Binding DerivedCol}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Id}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
<StackPanel Margin="5" Orientation="Horizontal">
<TextBlock Text="Original CollectionChanged Count" />
<TextBlock Margin="5,0,0,0" Text="{Binding CollectionChangedCount}" />
</StackPanel>
</StackPanel>
</Grid>
</Window>
using System;
using System.Collections.Specialized;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
using ReactiveUI;
namespace WpfApplication3
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
}
public class Model : ReactiveObject
{
static int _UniqueId;
public int Id { get; private set; }
public Model()
{
Id = _UniqueId++;
}
}
public class MainViewModel : ReactiveObject
{
ReactiveCollection<Model> _Col;
public ReactiveCollection<Model> Col
{
get { return _Col; }
set { this.RaiseAndSetIfChanged(x => x.Col, value); }
}
ReactiveCollection<Model> _DerivedCol;
public ReactiveCollection<Model> DerivedCol
{
get { return _DerivedCol; }
set { this.RaiseAndSetIfChanged(x => x.DerivedCol, value); }
}
int _CollectionChangedCount;
public int CollectionChangedCount
{
get { return _CollectionChangedCount; }
set { this.RaiseAndSetIfChanged(x => x.CollectionChangedCount, value); }
}
int _ManualCount;
public int ManualCount
{
get { return _ManualCount; }
set { this.RaiseAndSetIfChanged(x => x.ManualCount, value); }
}
int _ManualDerivedCount;
public int ManualDerivedCount
{
get { return _ManualDerivedCount; }
set { this.RaiseAndSetIfChanged(x => x.ManualDerivedCount, value); }
}
public MainViewModel()
{
// UI Thread
Col = new ReactiveCollection<Model>();
Col.CollectionChanged += (sender, args) => {
if (args.Action == NotifyCollectionChangedAction.Add) CollectionChangedCount++;
};
DerivedCol = new ReactiveCollection<Model>();
Col.ItemsAdded.Subscribe(x => DerivedCol.Add(x));
Col.ItemsRemoved.Subscribe(x => DerivedCol.Remove(x));
// Add single item - Works
Col.Add(new Model());
UpdateManualCounts();
// Add range - Fails
Col.AddRange(new[] { new Model(), new Model() });
UpdateManualCounts();
// Worker Thread
Task.Factory.StartNew(() =>
{
while (true)
{
// Add single item - Works
DispatcherInvoke(() => Col.Add(new Model()));
// Add Range - Fails in beginning, but magically starts working again
DispatcherInvoke(() => Col.AddRange(new[] { new Model(), new Model() }));
UpdateManualCounts();
Thread.Sleep(2000);
}
});
}
private void DispatcherInvoke(Action action)
{
Application.Current.Dispatcher.Invoke(action);
}
private void UpdateManualCounts()
{
ManualCount = Col.Count();
ManualDerivedCount = DerivedCol.Count();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment