Skip to content
NLNuvyntra Labs

Documentation

Lists and search

ObservableRangeCollection, SnapshotCollection for live inboxes, PagedCollection for catalogs, and SearchQuery.CommittedText.

ObservableRangeCollection

AddRange and ReplaceRange raise one CollectionChanged Reset. Do not Add in a loop for mid or large lists. Large lists must also virtualize in CollectionView. After a page is visible, prefer Add / Insert over ReplaceRange on Android BindableLayout.

var items = new ObservableRangeCollection<Product>();
items.AddRange(page);
items.ReplaceRange(next);

Pagination, snapshots, and search

PagedCollection<T> / DelegatePagedCollection<T> own load-more, refresh, and retry — not a live chat inbox. SnapshotCollection<T> loads once in InitializeAsync; later LoadAsync calls are no-ops unless force is true. After appear, mutate with AddLocal / Insert. Do not pair DelegatePagedCollection with CollectionView RemainingItemsThreshold when the fetch is sync. SearchQuery.Text binds to Entry; filter from CommittedText after debounce. Do not two-way bind SearchQuery to Android SearchBar.

public sealed class InboxViewModel : ViewModel
{
    public SnapshotCollection<Conversation> Inbox { get; }
    public SearchQuery Search { get; } = new();

    public InboxViewModel(IInbox catalog)
    {
        Inbox = new SnapshotCollection<Conversation>(
            ct => catalog.ListAsync(Search.CommittedText, ct));
    }

    protected override Task InitializeAsync(CancellationToken cancellationToken) =>
        Inbox.LoadAsync(cancellationToken: cancellationToken);
}

// catalog paging (not a live inbox)
await Products.RefreshAsync(ct);
await Products.LoadMoreAsync(ct);