Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #108 from reactiveui/rxcoll-resets

Expose Resets in ReactiveCollection
  • Loading branch information...
commit 0a9120b1157701f9202e642202288089415ab73f 2 parents f0ac101 + 69fcb46
Paul Betts authored
Showing with 67 additions and 1 deletion.
  1. +23 −0 ReactiveUI/Interfaces.cs
  2. +44 −1 ReactiveUI/ReactiveCollection.cs
View
23 ReactiveUI/Interfaces.cs
@@ -4,6 +4,7 @@
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq.Expressions;
+using System.Reactive;
using System.Reactive.Concurrency;
namespace ReactiveUI
@@ -184,6 +185,28 @@ public interface IReactiveCollection : IEnumerable, INotifyCollectionChanged
/// rebroadcast through ItemChanging/ItemChanged.
/// </summary>
bool ChangeTrackingEnabled { get; set; }
+
+ /// <summary>
+ /// This Observable is equivalent to the NotifyCollectionChanged event,
+ /// but fires before the collection is changed
+ /// </summary>
+ IObservable<NotifyCollectionChangedEventArgs> Changing { get; }
+
+ /// <summary>
+ /// This Observable is equivalent to the NotifyCollectionChanged event,
+ /// and fires after the collection is changed
+ /// </summary>
+ IObservable<NotifyCollectionChangedEventArgs> Changed { get; }
+
+ /// <summary>
+ /// This Observable is fired when a ShouldReset fires on the collection. This
+ /// means that you should forget your previous knowledge of the state
+ /// of the collection and reread it.
+ ///
+ /// This does *not* mean Clear, and if you interpret it as such, you are
+ /// Doing It Wrong.
+ /// </summary>
+ IObservable<Unit> ShouldReset { get; }
}
/// <summary>
View
45 ReactiveUI/ReactiveCollection.cs
@@ -39,6 +39,9 @@ public class ReactiveCollection<T> : Collection<T>, IReactiveCollection<T>
[IgnoreDataMember] Dictionary<object, RefcountDisposeWrapper> _propertyChangeWatchers = null;
+ [IgnoreDataMember] int _resetSubCount = 0;
+ static bool _hasWhinedAboutNoResetSub = false;
+
// NB: This exists so the serializer doesn't whine
public ReactiveCollection() : this(null) { }
@@ -182,7 +185,7 @@ protected override void ClearItems()
/*
- * List<T> methods we can make faster by possibly sending Reset
+ * List<T> methods we can make faster by possibly sending ShouldReset
* notifications instead of thrashing the UI by readding items
* one at a time
*/
@@ -278,6 +281,13 @@ public IDisposable SuppressChangeNotifications()
{
Interlocked.Increment(ref _suppressionRefCount);
+ if (!_hasWhinedAboutNoResetSub && _resetSubCount == 0) {
+ LogHost.Default.Warn("SuppressChangeNotifications was called (perhaps via AddRange), yet you do not");
+ LogHost.Default.Warn("have a subscription to ShouldReset. This probably isn't what you want, as ItemsAdded");
+ LogHost.Default.Warn("and friends will appear to 'miss' items");
+ _hasWhinedAboutNoResetSub = true;
+ }
+
return Disposable.Create(() => {
if (Interlocked.Decrement(ref _suppressionRefCount) == 0) {
Reset();
@@ -332,6 +342,28 @@ public IDisposable SuppressChangeNotifications()
get { return _changed.Select(_ => _inner.Count == 0).DistinctUntilChanged(); }
}
+ public IObservable<NotifyCollectionChangedEventArgs> Changing {
+ get { return _changing; }
+ }
+
+ public IObservable<NotifyCollectionChangedEventArgs> Changed {
+ get { return _changed; }
+ }
+
+ public IObservable<Unit> ShouldReset {
+ get {
+ return refcountSubscribers(_changed.SelectMany(x =>
+ x.Action != NotifyCollectionChangedAction.Reset ?
+ Observable.Empty<Unit>() :
+ Observable.Return(Unit.Default)), x => _resetSubCount += x);
+ }
+ }
+
+
+ /*
+ * Property Change Tracking
+ */
+
void addItemToPropertyTracking(T toTrack)
{
var item = toTrack as IReactiveNotifyPropertyChanged;
@@ -368,6 +400,17 @@ void clearAllPropertyChangeWatchers()
{
while (_propertyChangeWatchers.Count > 0) _propertyChangeWatchers.Values.First().Release();
}
+
+ static IObservable<TObs> refcountSubscribers<TObs>(IObservable<TObs> input, Action<int> block)
+ {
+ return Observable.Create<TObs>(subj => {
+ block(1);
+
+ return new CompositeDisposable(
+ input.Subscribe(subj),
+ Disposable.Create(() => block(-1)));
+ });
+ }
}
public static class ReactiveCollectionMixins
Please sign in to comment.
Something went wrong with that request. Please try again.