DevBitsLab.Feeds.WinUI 0.0.11

dotnet add package DevBitsLab.Feeds.WinUI --version 0.0.11
                    
NuGet\Install-Package DevBitsLab.Feeds.WinUI -Version 0.0.11
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DevBitsLab.Feeds.WinUI" Version="0.0.11" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DevBitsLab.Feeds.WinUI" Version="0.0.11" />
                    
Directory.Packages.props
<PackageReference Include="DevBitsLab.Feeds.WinUI" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add DevBitsLab.Feeds.WinUI --version 0.0.11
                    
#r "nuget: DevBitsLab.Feeds.WinUI, 0.0.11"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package DevBitsLab.Feeds.WinUI@0.0.11
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=DevBitsLab.Feeds.WinUI&version=0.0.11
                    
Install as a Cake Addin
#tool nuget:?package=DevBitsLab.Feeds.WinUI&version=0.0.11
                    
Install as a Cake Tool

DevBitsLab.Feeds.WinUI

WinUI extensions for DevBitsLab.Feeds, providing virtualized list loading support via ISupportIncrementalLoading.

NuGet .NET 10

πŸ“¦ Installation

dotnet add package DevBitsLab.Feeds.WinUI

Note: This package requires DevBitsLab.Feeds as a dependency (installed automatically).

πŸš€ Quick Start

IncrementalListFeed

IncrementalListFeed<T> implements ISupportIncrementalLoading for efficient virtualized loading in WinUI ListView, GridView, and other list controls.

using DevBitsLab.Feeds.WinUI;

public partial class ProductsViewModel : ObservableObject
{
    public IncrementalListFeed<Product> Products { get; }

    public ProductsViewModel(IProductService productService)
    {
        Products = new IncrementalListFeed<Product>(async (count, ct) =>
        {
            // Load items on-demand as user scrolls
            var products = await productService.GetProductsAsync(
                skip: Products.Count,
                take: (int)count,
                cancellationToken: ct);
            
            // Return items and whether more are available
            return (products, hasMore: products.Count == count);
        });
    }
}

XAML Binding

IncrementalListFeed<T> implements INotifyCollectionChanged, so bind it directlyβ€”no ObservableCollection wrapper needed.

<ListView ItemsSource="{x:Bind ViewModel.Products}">
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="models:Product">
            <TextBlock Text="{x:Bind Name}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

That's it! The ListView will automatically call LoadMoreItemsAsync as the user scrolls.

πŸ“– How It Works

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        ListView                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  Item 1                                              β”‚    β”‚
β”‚  β”‚  Item 2                                              β”‚    β”‚
β”‚  β”‚  Item 3                                              β”‚    β”‚
β”‚  β”‚  Item 4  ← User scrolls here                         β”‚    β”‚
β”‚  β”‚  ...                                                 β”‚    β”‚
β”‚  β”‚  ────────────────────────────────────────────────    β”‚    β”‚
β”‚  β”‚  Loading more...  ← ISupportIncrementalLoading       β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
            LoadMoreItemsAsync(count: 20)
                              β”‚
                              β–Ό
         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
         β”‚  Your async loading function       β”‚
         β”‚  - Fetches from API                β”‚
         β”‚  - Returns (items, hasMore)        β”‚
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
         Items added to underlying ListFeed<T>
         INotifyCollectionChanged fired
         ListView updates automatically

πŸ”§ API Reference

IncrementalListFeed<T>

Constructor
public IncrementalListFeed(
    Func<uint, CancellationToken, Task<(IEnumerable<T> Items, bool HasMore)>> loadMoreAsync)
Parameter Description
loadMoreAsync Async function that loads items. Receives requested count and cancellation token, returns loaded items and whether more are available.
Properties
Property Type Description
Count int Number of items currently loaded
HasMoreItems bool Whether more items can be loaded
IsLoading bool Whether items are currently being loaded
InnerFeed ListFeed<T> Underlying feed for direct manipulation
this[int] T Indexer to access items
Methods
Method Description
LoadMoreItemsAsync(uint count) Loads more items (called automatically by ListView)
Reset() Clears all items and resets loading state
Dispose() Disposes the underlying feed
Events
Event Description
CollectionChanged Raised when items are added, removed, or reset

πŸ“‹ Common Patterns

Pagination with Page Numbers

private int _currentPage = 0;
private const int PageSize = 20;

Products = new IncrementalListFeed<Product>(async (count, ct) =>
{
    var products = await api.GetProductsAsync(
        page: _currentPage++,
        pageSize: PageSize,
        ct);
    
    return (products, hasMore: products.Count == PageSize);
});

Cursor-Based Pagination

private string? _cursor = null;

Products = new IncrementalListFeed<Product>(async (count, ct) =>
{
    var response = await api.GetProductsAsync(cursor: _cursor, limit: count, ct);
    _cursor = response.NextCursor;
    
    return (response.Items, hasMore: response.NextCursor != null);
});

Pull-to-Refresh

[RelayCommand]
private async Task RefreshAsync()
{
    _currentPage = 0;  // Reset pagination
    Products.Reset();  // Clear items and allow reloading
    
    // ListView will automatically load first page
}

Error Handling

Products = new IncrementalListFeed<Product>(async (count, ct) =>
{
    try
    {
        var products = await api.GetProductsAsync(skip: Products.Count, take: count, ct);
        return (products, hasMore: products.Count == count);
    }
    catch (HttpRequestException)
    {
        // Return empty with hasMore=true to allow retry
        return ([], hasMore: true);
    }
});

Accessing the Inner Feed

// Add item manually
Products.InnerFeed.Add(newProduct);

// Remove item
Products.InnerFeed.RemoveAt(index);

// Subscribe to typed changes
Products.InnerFeed.ItemsChanged += (s, e) =>
{
    if (e.Change is ListChange<Product>.ItemAdded added)
        Debug.WriteLine($"Added: {added.Item.Name}");
};

🎯 Best Practices

  1. Use with virtualized controls - IncrementalListFeed is designed for ListView, GridView, etc. that support ISupportIncrementalLoading.

  2. Handle cancellation - Always pass the CancellationToken to your async operations.

  3. Return accurate hasMore - The ListView stops requesting items when hasMore is false.

  4. Keep batch sizes reasonable - The ListView typically requests 20-50 items at a time.

  5. Dispose when done - Call Dispose() or use [BindableFeed] for automatic disposal.

Package Description
DevBitsLab.Feeds Core reactive feeds library

πŸ“„ License

MIT License - see LICENSE for details.

Product Compatible and additional computed target framework versions.
.NET net10.0-windows10.0.26100 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.0.11 90 1/20/2026
0.0.10 90 1/19/2026
0.0.9 89 1/19/2026
0.0.8 100 1/19/2026

Added FeedPresenter control with automatic state management (Loading, Error, Refreshing, Value), customizable templates, WinUI transitions, and built-in retry support. Also includes IncrementalListFeed<T> implementing ISupportIncrementalLoading for WinUI ListView virtualization.