11
11
using System . Threading ;
12
12
using Splat ;
13
13
using System . Reactive . Concurrency ;
14
+ using System . Linq ;
14
15
15
16
namespace ReactiveUI
16
17
{
@@ -212,25 +213,22 @@ public ReactiveDerivedCollection(
212
213
this . selector = selector ;
213
214
this . filter = filter ;
214
215
this . orderer = orderer ;
215
- this . onRemoved = onRemoved ;
216
+ this . onRemoved = onRemoved ?? ( _ => { } ) ;
216
217
this . signalReset = signalReset ;
217
218
this . scheduler = scheduler ;
218
219
219
220
this . inner = new CompositeDisposable ( ) ;
220
221
this . indexToSourceIndexMap = new List < int > ( ) ;
221
222
this . sourceCopy = new List < TSource > ( ) ;
222
223
223
- if ( this . onRemoved != null )
224
- {
225
- this . inner . Add ( Disposable . Create ( ( ) =>
226
- {
227
- foreach ( var item in this )
228
- {
229
- this . onRemoved ( item ) ;
230
- }
231
- } ) ) ;
232
- }
233
-
224
+ if ( onRemoved != null ) {
225
+ this . inner . Add ( Disposable . Create ( ( ) => {
226
+ foreach ( var item in this ) {
227
+ this . onRemoved ( item ) ;
228
+ }
229
+ } ) ) ;
230
+ }
231
+
234
232
this . addAllItemsFromSourceCollection ( ) ;
235
233
this . wireUpChangeNotifications ( ) ;
236
234
}
@@ -382,10 +380,7 @@ void internalReplace(int destinationIndex, TValue newItem)
382
380
{
383
381
var item = this [ destinationIndex ] ;
384
382
base . SetItem ( destinationIndex , newItem ) ;
385
- if ( this . onRemoved != null )
386
- {
387
- onRemoved ( item ) ;
388
- }
383
+ onRemoved ( item ) ;
389
384
}
390
385
391
386
/// <summary>
@@ -590,16 +585,14 @@ protected override void internalClear()
590
585
{
591
586
indexToSourceIndexMap . Clear ( ) ;
592
587
sourceCopy . Clear ( ) ;
588
+
589
+ var items = this . ToArray ( ) ;
590
+
591
+ base . internalClear ( ) ;
593
592
594
- if ( this . onRemoved != null )
595
- {
596
- foreach ( var item in this )
597
- {
598
- onRemoved ( item ) ;
599
- }
593
+ foreach ( var item in items ) {
594
+ onRemoved ( item ) ;
600
595
}
601
-
602
- base . internalClear ( ) ;
603
596
}
604
597
605
598
void internalInsertAndMap ( int sourceIndex , TValue value )
@@ -615,10 +608,7 @@ protected override void internalRemoveAt(int destinationIndex)
615
608
indexToSourceIndexMap . RemoveAt ( destinationIndex ) ;
616
609
var item = this [ destinationIndex ] ;
617
610
base . internalRemoveAt ( destinationIndex ) ;
618
- if ( this . onRemoved != null )
619
- {
620
- onRemoved ( item ) ;
621
- }
611
+ onRemoved ( item ) ;
622
612
}
623
613
624
614
/// <summary>
@@ -889,6 +879,8 @@ public static class ObservableCollectionMixin
889
879
/// </summary>
890
880
/// <param name="selector">A Select function that will be run on each
891
881
/// item.</param>
882
+ /// <param name="onRemoved">An action that is called on each item when
883
+ /// it is removed.</param>
892
884
/// <param name="filter">A filter to determine whether to exclude items
893
885
/// in the derived collection.</param>
894
886
/// <param name="orderer">A comparator method to determine the ordering of
@@ -902,9 +894,9 @@ public static class ObservableCollectionMixin
902
894
public static IReactiveDerivedList < TNew > CreateDerivedCollection < T , TNew , TDontCare > (
903
895
this IEnumerable < T > This ,
904
896
Func < T , TNew > selector ,
897
+ Action < TNew > onRemoved ,
905
898
Func < T , bool > filter = null ,
906
899
Func < TNew , TNew , int > orderer = null ,
907
- Action < TNew > onRemoved = null ,
908
900
IObservable < TDontCare > signalReset = null ,
909
901
IScheduler scheduler = null )
910
902
{
@@ -923,6 +915,74 @@ public static IReactiveDerivedList<TNew> CreateDerivedCollection<T, TNew, TDontC
923
915
return new ReactiveDerivedCollection < T , TNew > ( This , selector , filter , orderer , onRemoved , reset , scheduler ) ;
924
916
}
925
917
918
+ /// <summary>
919
+ /// Creates a collection whose contents will "follow" another
920
+ /// collection; this method is useful for creating ViewModel collections
921
+ /// that are automatically updated when the respective Model collection
922
+ /// is updated.
923
+ ///
924
+ /// Note that even though this method attaches itself to any
925
+ /// IEnumerable, it will only detect changes from objects implementing
926
+ /// INotifyCollectionChanged (like ReactiveList). If your source
927
+ /// collection doesn't implement this, signalReset is the way to signal
928
+ /// the derived collection to reorder/refilter itself.
929
+ /// </summary>
930
+ /// <param name="selector">A Select function that will be run on each
931
+ /// item.</param>
932
+ /// <param name="filter">A filter to determine whether to exclude items
933
+ /// in the derived collection.</param>
934
+ /// <param name="orderer">A comparator method to determine the ordering of
935
+ /// the resulting collection.</param>
936
+ /// <param name="signalReset">When this Observable is signalled,
937
+ /// the derived collection will be manually
938
+ /// reordered/refiltered.</param>
939
+ /// <returns>A new collection whose items are equivalent to
940
+ /// Collection.Select().Where().OrderBy() and will mirror changes
941
+ /// in the initial collection.</returns>
942
+ public static IReactiveDerivedList < TNew > CreateDerivedCollection < T , TNew , TDontCare > (
943
+ this IEnumerable < T > This ,
944
+ Func < T , TNew > selector ,
945
+ Func < T , bool > filter = null ,
946
+ Func < TNew , TNew , int > orderer = null ,
947
+ IObservable < TDontCare > signalReset = null ,
948
+ IScheduler scheduler = null )
949
+ {
950
+ return This . CreateDerivedCollection ( selector , ( Action < TNew > ) null , filter , orderer , signalReset , scheduler ) ;
951
+ }
952
+
953
+ /// <summary>
954
+ /// Creates a collection whose contents will "follow" another
955
+ /// collection; this method is useful for creating ViewModel collections
956
+ /// that are automatically updated when the respective Model collection
957
+ /// is updated.
958
+ ///
959
+ /// Be aware that this overload will result in a collection that *only*
960
+ /// updates if the source implements INotifyCollectionChanged. If your
961
+ /// list changes but isn't a ReactiveList/ObservableCollection,
962
+ /// you probably want to use the other overload.
963
+ /// </summary>
964
+ /// <param name="selector">A Select function that will be run on each
965
+ /// item.</param>
966
+ /// <param name="onRemoved">An action that is called on each item when
967
+ /// it is removed.</param>
968
+ /// <param name="filter">A filter to determine whether to exclude items
969
+ /// in the derived collection.</param>
970
+ /// <param name="orderer">A comparator method to determine the ordering of
971
+ /// the resulting collection.</param>
972
+ /// <returns>A new collection whose items are equivalent to
973
+ /// Collection.Select().Where().OrderBy() and will mirror changes
974
+ /// in the initial collection.</returns>
975
+ public static IReactiveDerivedList < TNew > CreateDerivedCollection < T , TNew > (
976
+ this IEnumerable < T > This ,
977
+ Func < T , TNew > selector ,
978
+ Action < TNew > onRemoved ,
979
+ Func < T , bool > filter = null ,
980
+ Func < TNew , TNew , int > orderer = null ,
981
+ IScheduler scheduler = null )
982
+ {
983
+ return This . CreateDerivedCollection ( selector , onRemoved , filter , orderer , ( IObservable < Unit > ) null , scheduler ) ;
984
+ }
985
+
926
986
/// <summary>
927
987
/// Creates a collection whose contents will "follow" another
928
988
/// collection; this method is useful for creating ViewModel collections
@@ -948,10 +1008,10 @@ public static IReactiveDerivedList<TNew> CreateDerivedCollection<T, TNew>(
948
1008
Func < T , TNew > selector ,
949
1009
Func < T , bool > filter = null ,
950
1010
Func < TNew , TNew , int > orderer = null ,
951
- Action < TNew > onRemoved = null ,
952
1011
IScheduler scheduler = null )
953
1012
{
954
- return This . CreateDerivedCollection ( selector , filter , orderer , onRemoved , ( IObservable < Unit > ) null , scheduler ) ;
1013
+ return This . CreateDerivedCollection ( selector , ( Action < TNew > ) null , filter , orderer , ( IObservable < Unit > ) null , scheduler ) ;
955
1014
}
1015
+
956
1016
}
957
1017
}
0 commit comments