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
<PackageReference Include="DevBitsLab.Feeds.WinUI" Version="0.0.11" />
<PackageVersion Include="DevBitsLab.Feeds.WinUI" Version="0.0.11" />
<PackageReference Include="DevBitsLab.Feeds.WinUI" />
paket add DevBitsLab.Feeds.WinUI --version 0.0.11
#r "nuget: DevBitsLab.Feeds.WinUI, 0.0.11"
#:package DevBitsLab.Feeds.WinUI@0.0.11
#addin nuget:?package=DevBitsLab.Feeds.WinUI&version=0.0.11
#tool nuget:?package=DevBitsLab.Feeds.WinUI&version=0.0.11
DevBitsLab.Feeds.WinUI
WinUI extensions for DevBitsLab.Feeds, providing virtualized list loading support via ISupportIncrementalLoading.
π¦ Installation
dotnet add package DevBitsLab.Feeds.WinUI
Note: This package requires
DevBitsLab.Feedsas 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
Use with virtualized controls -
IncrementalListFeedis designed forListView,GridView, etc. that supportISupportIncrementalLoading.Handle cancellation - Always pass the
CancellationTokento your async operations.Return accurate
hasMore- The ListView stops requesting items whenhasMoreisfalse.Keep batch sizes reasonable - The ListView typically requests 20-50 items at a time.
Dispose when done - Call
Dispose()or use[BindableFeed]for automatic disposal.
π¦ Related Packages
| Package | Description |
|---|---|
| DevBitsLab.Feeds | Core reactive feeds library |
π License
MIT License - see LICENSE for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0-windows10.0.26100 is compatible. |
-
net10.0-windows10.0.26100
- DevBitsLab.Feeds (>= 0.0.11)
- Microsoft.WindowsAppSDK (>= 1.7.250310001)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
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.