Skip to content

Commit b0a4578

Browse files
committed
Merge branch 'rxui5-master' of https://github.com/reactiveui/ReactiveUI into rxui5-master
2 parents 6a3c36b + f58c66c commit b0a4578

File tree

5 files changed

+146
-69
lines changed

5 files changed

+146
-69
lines changed

ReactiveUI.Tests/ReactiveCollectionTest.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ public void CreateCollectionWithTimer()
324324
var sched = new TestScheduler();
325325

326326
using (TestUtils.WithScheduler(sched)) {
327-
ReactiveList<string> fixture;
327+
IReactiveDerivedList<string> fixture;
328328

329329
fixture = input.ToObservable(sched).CreateCollection(TimeSpan.FromSeconds(0.5));
330330
sched.AdvanceToMs(1005);
@@ -831,7 +831,7 @@ public virtual void Test() { }
831831
public class DerivedCollectionTestContainer<TSource, TValue> : DerivedCollectionTestContainer
832832
{
833833
public IEnumerable<TSource> Source { get; set; }
834-
public ReactiveDerivedCollection<TValue> Derived { get; set; }
834+
public IReactiveDerivedList<TValue> Derived { get; set; }
835835
public Func<TSource, TValue> Selector { get; set; }
836836
public Func<TSource, bool> Filter { get; set; }
837837
public IComparer<TValue> Orderer { get; set; }

ReactiveUI.Tests/ReactiveCommandTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ public void RegisterAsyncFunctionSmokeTest()
164164
{
165165
(new TestScheduler()).With(sched => {
166166
var fixture = new ReactiveCommand();
167-
ReactiveList<int> results;
167+
IReactiveDerivedList<int> results;
168168

169169
results = fixture.RegisterAsync(_ =>
170170
Observable.Return(5).Delay(TimeSpan.FromSeconds(5), sched)).CreateCollection();

ReactiveUI/Interfaces.cs

Lines changed: 127 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace ReactiveUI
1515
/// will be Covariant which will allow simpler casting between specific and
1616
/// generic changes.
1717
/// </summary>
18-
public interface IObservedChange<TSender, TValue>
18+
public interface IObservedChange<out TSender, out TValue>
1919
{
2020
/// <summary>
2121
/// The object that has raised the change.
@@ -81,7 +81,7 @@ public interface IReactiveNotifyPropertyChanged : INotifyPropertyChanged, INotif
8181
/// IReactiveNotifyPropertyChanged of TSender is a helper interface that adds
8282
/// typed versions of Changing and Changed.
8383
/// </summary>
84-
public interface IReactiveNotifyPropertyChanged<TSender> : IReactiveNotifyPropertyChanged
84+
public interface IReactiveNotifyPropertyChanged<out TSender> : IReactiveNotifyPropertyChanged
8585
{
8686
new IObservable<IObservedChange<TSender, object>> Changing { get; }
8787
new IObservable<IObservedChange<TSender, object>> Changed { get; }
@@ -166,78 +166,111 @@ public interface IReactiveCommand : IHandleObservableErrors, IObservable<object>
166166
/// IReactiveNotifyPropertyChanged semantically as "Fire when *anything* in
167167
/// the collection or any of its items have changed, in any way".
168168
/// </summary>
169-
public interface IReactiveCollection : ICollection, INotifyCollectionChanged, INotifyPropertyChanging, INotifyPropertyChanged, IEnableLogger
169+
public interface IReactiveCollection : IReactiveNotifyCollectionChanged, IReactiveNotifyCollectionItemChanged, ICollection, INotifyPropertyChanging, INotifyPropertyChanged, IEnableLogger
170170
{
171-
//
172-
// Collection Tracking
173-
//
171+
}
172+
173+
/// <summary>
174+
/// IReactiveCollection of T is the typed version of IReactiveCollection and
175+
/// adds type-specified versions of Observables
176+
/// </summary>
177+
public interface IReactiveCollection<T> : IReactiveCollection, ICollection<T>, IReactiveNotifyCollectionChanged<T>, IReactiveNotifyCollectionItemChanged<T>
178+
{
179+
}
174180

181+
/// <summary>
182+
/// IReactiveNotifyCollectionItemChanged provides notifications for collection item updates, ie when an object in
183+
/// a collection changes.
184+
/// </summary>
185+
public interface IReactiveNotifyCollectionItemChanged
186+
{
175187
/// <summary>
176-
/// Fires when items are added to the collection, once per item added.
177-
/// Functions that add multiple items such AddRange should fire this
178-
/// multiple times. The object provided is the item that was added.
188+
/// Provides Item Changing notifications for any item in collection that
189+
/// implements IReactiveNotifyPropertyChanged. This is only enabled when
190+
/// ChangeTrackingEnabled is set to True.
179191
/// </summary>
180-
IObservable<object> ItemsAdded { get; }
192+
IObservable<IObservedChange<object, object>> ItemChanging { get; }
181193

182194
/// <summary>
183-
/// Fires before an item is going to be added to the collection.
195+
/// Provides Item Changed notifications for any item in collection that
196+
/// implements IReactiveNotifyPropertyChanged. This is only enabled when
197+
/// ChangeTrackingEnabled is set to True.
184198
/// </summary>
185-
IObservable<object> BeforeItemsAdded { get; }
199+
IObservable<IObservedChange<object, object>> ItemChanged { get; }
186200

187201
/// <summary>
188-
/// Fires once an item has been removed from a collection, providing the
189-
/// item that was removed.
202+
/// Enables the ItemChanging and ItemChanged properties; when this is
203+
/// enabled, whenever a property on any object implementing
204+
/// IReactiveNotifyPropertyChanged changes, the change will be
205+
/// rebroadcast through ItemChanging/ItemChanged.
190206
/// </summary>
191-
IObservable<object> ItemsRemoved { get; }
207+
bool ChangeTrackingEnabled { get; set; }
208+
}
192209

210+
/// <summary>
211+
/// IReactiveNotifyCollectionItemChanged of T is the typed version of IReactiveNotifyCollectionItemChanged and
212+
/// adds type-specified versions of Observables
213+
/// </summary>
214+
public interface IReactiveNotifyCollectionItemChanged<out T> : IReactiveNotifyCollectionItemChanged
215+
{
193216
/// <summary>
194-
/// Fires before an item will be removed from a collection, providing
195-
/// the item that will be removed.
217+
/// Provides Item Changing notifications for any item in collection that
218+
/// implements IReactiveNotifyPropertyChanged. This is only enabled when
219+
/// ChangeTrackingEnabled is set to True.
196220
/// </summary>
197-
IObservable<object> BeforeItemsRemoved { get; }
221+
new IObservable<IObservedChange<T, object>> ItemChanging { get; }
198222

199223
/// <summary>
200-
/// Fires whenever the number of items in a collection has changed,
201-
/// providing the new Count.
224+
/// Provides Item Changed notifications for any item in collection that
225+
/// implements IReactiveNotifyPropertyChanged. This is only enabled when
226+
/// ChangeTrackingEnabled is set to True.
202227
/// </summary>
203-
IObservable<int> CountChanged { get; }
228+
new IObservable<IObservedChange<T, object>> ItemChanged { get; }
229+
}
204230

231+
/// <summary>
232+
/// IReactiveCollection provides notifications when the contents
233+
/// of collection are changed (items are added/removed/moved).
234+
/// </summary>
235+
public interface IReactiveNotifyCollectionChanged : INotifyCollectionChanged
236+
{
205237
/// <summary>
206-
/// Fires before a collection is about to change, providing the previous
207-
/// Count.
238+
/// Fires when items are added to the collection, once per item added.
239+
/// Functions that add multiple items such AddRange should fire this
240+
/// multiple times. The object provided is the item that was added.
208241
/// </summary>
209-
IObservable<int> CountChanging { get; }
242+
IObservable<object> ItemsAdded { get; }
210243

211244
/// <summary>
212-
/// Fires when a collection becomes or stops being empty.
245+
/// Fires before an item is going to be added to the collection.
213246
/// </summary>
214-
IObservable<bool> IsEmptyChanged { get; }
247+
IObservable<object> BeforeItemsAdded { get; }
215248

216-
//
217-
// Change Tracking
218-
//
249+
/// <summary>
250+
/// Fires once an item has been removed from a collection, providing the
251+
/// item that was removed.
252+
/// </summary>
253+
IObservable<object> ItemsRemoved { get; }
219254

220255
/// <summary>
221-
/// Provides Item Changing notifications for any item in collection that
222-
/// implements IReactiveNotifyPropertyChanged. This is only enabled when
223-
/// ChangeTrackingEnabled is set to True.
256+
/// Fires before an item will be removed from a collection, providing
257+
/// the item that will be removed.
224258
/// </summary>
225-
IObservable<IObservedChange<object, object>> ItemChanging { get; }
259+
IObservable<object> BeforeItemsRemoved { get; }
226260

227261
/// <summary>
228-
/// Provides Item Changed notifications for any item in collection that
229-
/// implements IReactiveNotifyPropertyChanged. This is only enabled when
230-
/// ChangeTrackingEnabled is set to True.
262+
/// Fires before an items moves from one position in the collection to
263+
/// another, providing the item(s) to be moved as well as source and destination
264+
/// indices.
231265
/// </summary>
232-
IObservable<IObservedChange<object, object>> ItemChanged { get; }
266+
IObservable<IMoveInfo<object>> BeforeItemsMoved { get; }
233267

234268
/// <summary>
235-
/// Enables the ItemChanging and ItemChanged properties; when this is
236-
/// enabled, whenever a property on any object implementing
237-
/// IReactiveNotifyPropertyChanged changes, the change will be
238-
/// rebroadcast through ItemChanging/ItemChanged.
269+
/// Fires once one or more items moves from one position in the collection to
270+
/// another, providing the item(s) that was moved as well as source and destination
271+
/// indices.
239272
/// </summary>
240-
bool ChangeTrackingEnabled { get; set; }
273+
IObservable<IMoveInfo<object>> ItemsMoved { get; }
241274

242275
/// <summary>
243276
/// This Observable is equivalent to the NotifyCollectionChanged event,
@@ -263,10 +296,10 @@ public interface IReactiveCollection : ICollection, INotifyCollectionChanged, IN
263296
}
264297

265298
/// <summary>
266-
/// IReactiveCollection of T is the typed version of IReactiveCollection and
299+
/// IReactiveNotifyCollectionChanged of T is the typed version of IReactiveNotifyCollectionChanged and
267300
/// adds type-specified versions of Observables
268301
/// </summary>
269-
public interface IReactiveCollection<T> : ICollection<T>, IReactiveCollection
302+
public interface IReactiveNotifyCollectionChanged<out T> : IReactiveNotifyCollectionChanged
270303
{
271304
/// <summary>
272305
/// Fires when items are added to the collection, once per item added.
@@ -293,27 +326,68 @@ public interface IReactiveCollection<T> : ICollection<T>, IReactiveCollection
293326
new IObservable<T> BeforeItemsRemoved { get; }
294327

295328
/// <summary>
296-
/// Provides Item Changing notifications for any item in collection that
297-
/// implements IReactiveNotifyPropertyChanged. This is only enabled when
298-
/// ChangeTrackingEnabled is set to True.
329+
/// Fires before an items moves from one position in the collection to
330+
/// another, providing the item(s) to be moved as well as source and destination
331+
/// indices.
299332
/// </summary>
300-
new IObservable<IObservedChange<T, object>> ItemChanging { get; }
333+
new IObservable<IMoveInfo<T>> BeforeItemsMoved { get; }
301334

302335
/// <summary>
303-
/// Provides Item Changed notifications for any item in collection that
304-
/// implements IReactiveNotifyPropertyChanged. This is only enabled when
305-
/// ChangeTrackingEnabled is set to True.
336+
/// Fires once one or more items moves from one position in the collection to
337+
/// another, providing the item(s) that was moved as well as source and destination
338+
/// indices.
306339
/// </summary>
307-
new IObservable<IObservedChange<T, object>> ItemChanged { get; }
340+
new IObservable<IMoveInfo<T>> ItemsMoved { get; }
308341
}
309342

310343
/// <summary>
311-
/// An IList that reports change notifications
344+
/// IReadOnlyReactiveCollection represents a read-only collection that can notify when its
345+
/// contents are changed (either items are added/removed, or the object
346+
/// itself changes).
347+
///
348+
/// It is important to implement the Changing/Changed from
349+
/// IReactiveNotifyPropertyChanged semantically as "Fire when *anything* in
350+
/// the collection or any of its items have changed, in any way".
351+
/// </summary>
352+
public interface IReadOnlyReactiveCollection<out T> : IReadOnlyCollection<T>, IReactiveNotifyCollectionChanged<T>, IReactiveNotifyCollectionItemChanged<T>, INotifyPropertyChanging, INotifyPropertyChanged, IEnableLogger
353+
{
354+
}
355+
356+
/// <summary>
357+
/// IReactiveList represents a list that can notify when its
358+
/// contents are changed (either items are added/removed, or the object
359+
/// itself changes).
360+
///
361+
/// It is important to implement the Changing/Changed from
362+
/// IReactiveNotifyPropertyChanged semantically as "Fire when *anything* in
363+
/// the collection or any of its items have changed, in any way".
312364
/// </summary>
313365
public interface IReactiveList<T> : IReactiveCollection<T>, IList<T>, IList
314366
{
315367
}
316368

369+
/// <summary>
370+
/// IReactiveList represents a read-only list that can notify when its
371+
/// contents are changed (either items are added/removed, or the object
372+
/// itself changes).
373+
///
374+
/// It is important to implement the Changing/Changed from
375+
/// IReactiveNotifyPropertyChanged semantically as "Fire when *anything* in
376+
/// the collection or any of its items have changed, in any way".
377+
/// </summary>
378+
public interface IReadOnlyReactiveList<out T> : IReadOnlyReactiveCollection<T>, IReadOnlyList<T>
379+
{
380+
}
381+
382+
/// <summary>
383+
/// IReactiveDerivedList repreents a collection whose contents will "follow" another
384+
/// collection; this method is useful for creating ViewModel collections
385+
/// that are automatically updated when the respective Model collection is updated.
386+
/// </summary>
387+
public interface IReactiveDerivedList<T> : IReadOnlyReactiveList<T>, IDisposable
388+
{
389+
}
390+
317391
// NB: This is just a name we can bolt extension methods to
318392
public interface INavigateCommand : IReactiveCommand { }
319393

ReactiveUI/ReactiveCollectionMixins.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace ReactiveUI
1818
/// It is read-only, and any attempts to change items in the collection will
1919
/// fail.
2020
/// </summary>
21-
public abstract class ReactiveDerivedCollection<TValue> : ReactiveList<TValue>, IDisposable
21+
internal abstract class ReactiveDerivedCollection<TValue> : ReactiveList<TValue>, IReactiveDerivedList<TValue>, IDisposable
2222
{
2323
const string readonlyExceptionMessage = "Derived collections cannot be modified.";
2424

@@ -176,7 +176,7 @@ public virtual void Dispose(bool disposing) { }
176176
/// It is read-only, and any attempts to change items in the collection will
177177
/// fail.
178178
/// </summary>
179-
public sealed class ReactiveDerivedCollection<TSource, TValue> : ReactiveDerivedCollection<TValue>, IDisposable
179+
internal sealed class ReactiveDerivedCollection<TSource, TValue> : ReactiveDerivedCollection<TValue>, IDisposable
180180
{
181181
readonly IEnumerable<TSource> source;
182182
readonly Func<TSource, TValue> selector;
@@ -798,7 +798,7 @@ public static class ReactiveCollectionMixins
798798
/// collection no faster than the delay provided.</param>
799799
/// <returns>A new collection which will be populated with the
800800
/// Observable.</returns>
801-
public static ReactiveDerivedCollection<T> CreateCollection<T>(
801+
public static IReactiveDerivedList<T> CreateCollection<T>(
802802
this IObservable<T> fromObservable,
803803
TimeSpan? withDelay = null,
804804
Action<Exception> onError = null)
@@ -821,7 +821,7 @@ public static ReactiveDerivedCollection<T> CreateCollection<T>(
821821
/// collection no faster than the delay provided.</param>
822822
/// <returns>A new collection which will be populated with the
823823
/// Observable.</returns>
824-
public static ReactiveDerivedCollection<TRet> CreateCollection<T, TRet>(
824+
public static IReactiveDerivedList<TRet> CreateCollection<T, TRet>(
825825
this IObservable<T> fromObservable,
826826
Func<T, TRet> selector,
827827
TimeSpan? withDelay = null)
@@ -857,7 +857,7 @@ public static class ObservableCollectionMixin
857857
/// <returns>A new collection whose items are equivalent to
858858
/// Collection.Select().Where().OrderBy() and will mirror changes
859859
/// in the initial collection.</returns>
860-
public static ReactiveDerivedCollection<TNew> CreateDerivedCollection<T, TNew, TDontCare>(
860+
public static IReactiveDerivedList<TNew> CreateDerivedCollection<T, TNew, TDontCare>(
861861
this IEnumerable<T> This,
862862
Func<T, TNew> selector,
863863
Func<T, bool> filter = null,
@@ -895,7 +895,7 @@ public static ReactiveDerivedCollection<TNew> CreateDerivedCollection<T, TNew, T
895895
/// <returns>A new collection whose items are equivalent to
896896
/// Collection.Select().Where().OrderBy() and will mirror changes
897897
/// in the initial collection.</returns>
898-
public static ReactiveDerivedCollection<TNew> CreateDerivedCollection<T, TNew>(
898+
public static IReactiveDerivedList<TNew> CreateDerivedCollection<T, TNew>(
899899
this IEnumerable<T> This,
900900
Func<T, TNew> selector,
901901
Func<T, bool> filter = null,

ReactiveUI/ReactiveList.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ namespace ReactiveUI
2020
{
2121
[DebuggerDisplay("Count = {Count}")]
2222
[DebuggerTypeProxy(typeof(CollectionDebugView<>))]
23-
public class ReactiveList<T> : IReactiveList<T>
23+
public class ReactiveList<T> : IReactiveList<T>, IReadOnlyReactiveList<T>
2424
{
2525
public event NotifyCollectionChangedEventHandler CollectionChanging;
2626
public event NotifyCollectionChangedEventHandler CollectionChanged;
@@ -376,13 +376,16 @@ public IDisposable SuppressChangeNotifications()
376376
public IObservable<IObservedChange<T, object>> ItemChanging { get { return _itemChanging.Value; } }
377377
public IObservable<IObservedChange<T, object>> ItemChanged { get { return _itemChanged.Value; } }
378378

379-
IObservable<object> IReactiveCollection.BeforeItemsAdded { get { return BeforeItemsAdded.Select(x => (object) x); } }
380-
IObservable<object> IReactiveCollection.ItemsAdded { get { return ItemsAdded.Select(x => (object) x); } }
379+
IObservable<object> IReactiveNotifyCollectionChanged.BeforeItemsAdded { get { return BeforeItemsAdded.Select(x => (object)x); } }
380+
IObservable<object> IReactiveNotifyCollectionChanged.ItemsAdded { get { return ItemsAdded.Select(x => (object)x); } }
381381

382-
IObservable<object> IReactiveCollection.BeforeItemsRemoved { get { return BeforeItemsRemoved.Select(x => (object) x); } }
383-
IObservable<object> IReactiveCollection.ItemsRemoved { get { return ItemsRemoved.Select(x => (object) x); } }
382+
IObservable<object> IReactiveNotifyCollectionChanged.BeforeItemsRemoved { get { return BeforeItemsRemoved.Select(x => (object)x); } }
383+
IObservable<object> IReactiveNotifyCollectionChanged.ItemsRemoved { get { return ItemsRemoved.Select(x => (object) x); } }
384384

385-
IObservable<IObservedChange<object, object>> IReactiveCollection.ItemChanging {
385+
IObservable<IMoveInfo<object>> IReactiveNotifyCollectionChanged.BeforeItemsMoved { get { return BeforeItemsMoved.Select(x => (IMoveInfo<object>)x); } }
386+
IObservable<IMoveInfo<object>> IReactiveNotifyCollectionChanged.ItemsMoved { get { return ItemsMoved.Select(x => (IMoveInfo<object>)x); } }
387+
388+
IObservable<IObservedChange<object, object>> IReactiveNotifyCollectionItemChanged.ItemChanging {
386389
get {
387390
return _itemChanging.Value.Select(x => (IObservedChange<object, object>) new ObservedChange<object, object>() {
388391
Sender = x.Sender,
@@ -392,7 +395,7 @@ IObservable<IObservedChange<object, object>> IReactiveCollection.ItemChanging {
392395
}
393396
}
394397

395-
IObservable<IObservedChange<object, object>> IReactiveCollection.ItemChanged {
398+
IObservable<IObservedChange<object, object>> IReactiveNotifyCollectionItemChanged.ItemChanged {
396399
get {
397400
return _itemChanged.Value.Select(x => (IObservedChange<object, object>) new ObservedChange<object, object>() {
398401
Sender = x.Sender,

0 commit comments

Comments
 (0)