public static void Reset <T>(this IReactiveList <T> @this, IEnumerable <T> items) { using (@this.SuppressChangeNotifications()) { @this.Clear(); @this.AddRange(items); } }
/// <summary> /// Adapts the specified changeset /// </summary> /// <param name="changes">The changes.</param> public void Adapt(IChangeSet <TObject, TKey> changes) { Clone(changes); if (changes.Count - changes.Refreshes > _resetThreshold || !_loaded) { _loaded = true; using (_target.SuppressChangeNotifications()) { _target.Clear(); _target.AddRange(_data.Values); } } else { DoUpdate(changes); } }
/// <summary> /// Takes each list produced by this observable and mirrors its contents in the target list. /// The target list is modified, not replaced. /// The type of the target list property is IReadOnlyReactiveList because it doesn't make sense to have a mutible list /// if this binding keeps changing the contents of the list, but the type of the actual object should be ReactiveList /// so the list can be modified by this binding. /// </summary> /// <typeparam name="TObj">The type of viewmodel</typeparam> /// <typeparam name="TListItem">The type of object contained in the list</typeparam> /// <param name="data">The observable to take lists from.</param> /// <param name="target">The viewmodel that is used as a base for finding the target list property</param> /// <param name="property">The IReactiveList property that will be modified.</param> /// <returns>A disposable to break the binding</returns> public static IDisposable BindListContents <TObj, TListItem>(this IObservable <IList <TListItem> > data, TObj target, Expression <Func <TObj, IReadOnlyReactiveList <TListItem> > > property) where TObj : class { IObservable <IReadOnlyReactiveList <TListItem> > targetListObservable = target.WhenAnyValue(property); return(Observable.CombineLatest(targetListObservable, data, (a, b) => (TargetList: a, SourceList: b)) .Subscribe(t => { IReactiveList <TListItem> latestTargetList = t.TargetList as IReactiveList <TListItem>; IList <TListItem> latestData = t.SourceList; if (latestTargetList == null) { return; } if (latestData == null) { latestTargetList.Clear(); return; } var changes = LongestCommonSubsequence.GetChanges(latestTargetList, latestData).ToArray(); if (changes.Length == 0) { return; } using (changes.Length > 1 ? latestTargetList.SuppressChangeNotifications() : Disposable.Empty) { foreach (var(index, item, changeType) in changes) { if (changeType == LongestCommonSubsequence.ChangeType.Removed) { latestTargetList.RemoveAt(index); } else if (changeType == LongestCommonSubsequence.ChangeType.Added) { latestTargetList.Insert(index, item); } } } })); }
public static Task SimpleCollectionLoad <T>(this IReactiveList <T> viewModel, GitHubRequest <List <T> > request, bool?forceDataRefresh, Action <Func <Task> > assignMore = null) where T : new() { if (assignMore == null) { assignMore = (x) => {} } ; return(viewModel.RequestModel(request, forceDataRefresh, response => { viewModel.CreateMore(response, assignMore, x => { // This is f*****g broken for iOS because it can't handle estimated rows and the insertions // that ReactiveUI seems to be producing using (viewModel.SuppressChangeNotifications()) { viewModel.AddRange(x); } }); viewModel.Reset(response.Data); })); } }