22// Roland Pheasant licenses this file to you under the MIT license.
33// See the LICENSE file in the project root for full license information.
44
5+ using System . ComponentModel ;
56using System . Reactive . Disposables ;
67using System . Reactive . Linq ;
78using DynamicData . Cache ;
@@ -30,15 +31,22 @@ public SortAndBind(IObservable<IChangeSet<TObject, TKey>> source,
3031 SortAndBindOptions options ,
3132 IList < TObject > target )
3233 {
34+ var scheduler = options . Scheduler ;
35+
3336 // static one time comparer
3437 var applicator = new SortApplicator ( _cache , target , comparer , options ) ;
3538
36- _sorted = source . Do ( changes =>
39+ if ( scheduler is not null )
40+ source = source . ObserveOn ( scheduler ) ;
41+
42+ _sorted = source . Select ( ( changes , index ) =>
3743 {
3844 // clone to local cache so that we can sort the entire set when threshold is over a certain size.
3945 _cache . Clone ( changes ) ;
4046
41- applicator . ProcessChanges ( changes ) ;
47+ applicator . ProcessChanges ( changes , index == 0 ) ;
48+
49+ return changes ;
4250 } ) ;
4351 }
4452
@@ -48,6 +56,14 @@ public SortAndBind(IObservable<IChangeSet<TObject, TKey>> source,
4856 IList < TObject > target )
4957 => _sorted = Observable . Create < IChangeSet < TObject , TKey > > ( observer =>
5058 {
59+ var scheduler = options . Scheduler ;
60+
61+ if ( scheduler is not null )
62+ {
63+ source = source . ObserveOn ( scheduler ) ;
64+ comparerChanged = comparerChanged . ObserveOn ( scheduler ) ;
65+ }
66+
5167 var locker = new object ( ) ;
5268 SortApplicator ? sortApplicator = null ;
5369
@@ -61,14 +77,17 @@ public SortAndBind(IObservable<IChangeSet<TObject, TKey>> source,
6177
6278 // Listen to changes and apply the sorting
6379 var subscriber = source . Synchronize ( locker )
64- . Do ( changes =>
80+ . Select ( ( changes , index ) =>
6581 {
6682 _cache . Clone ( changes ) ;
6783
6884 // the sort applicator will be null until the comparer change observable fires.
6985 if ( sortApplicator is not null )
70- sortApplicator . ProcessChanges ( changes ) ;
71- } ) . SubscribeSafe ( observer ) ;
86+ sortApplicator . ProcessChanges ( changes , index == 0 ) ;
87+
88+ return changes ;
89+ } )
90+ . SubscribeSafe ( observer ) ;
7291
7392 return new CompositeDisposable ( latestComparer , subscriber ) ;
7493 } ) ;
@@ -92,10 +111,12 @@ public void ApplySort()
92111 }
93112
94113 // apply sorting as a side effect of the observable stream.
95- public void ProcessChanges ( IChangeSet < TObject , TKey > changeSet )
114+ public void ProcessChanges ( IChangeSet < TObject , TKey > changeSet , bool isFirstTimeLoad )
96115 {
116+ var forceReset = isFirstTimeLoad && options . ResetOnFirstTimeLoad ;
117+
97118 // apply sorted changes to the target collection
98- if ( options . ResetThreshold > 0 && options . ResetThreshold < changeSet . Count )
119+ if ( forceReset || ( options . ResetThreshold > 0 && options . ResetThreshold < changeSet . Count ) )
99120 {
100121 Reset ( cache . Items . OrderBy ( t => t , comparer ) , true ) ;
101122 }
@@ -122,6 +143,15 @@ private void Reset(IEnumerable<TObject> sorted, bool fireReset)
122143 observableCollectionExtended . Load ( sorted ) ;
123144 }
124145 }
146+ else if ( fireReset && target is BindingList < TObject > bindingList )
147+ {
148+ // suspend count as it can result in a flood of binding updates.
149+ using ( new BindingListEventsSuspender < TObject > ( bindingList ) )
150+ {
151+ target . Clear ( ) ;
152+ target . AddRange ( sorted ) ;
153+ }
154+ }
125155 else
126156 {
127157 target . Clear ( ) ;
0 commit comments