RabstackQuery.Mvvm
0.3.0
dotnet add package RabstackQuery.Mvvm --version 0.3.0
NuGet\Install-Package RabstackQuery.Mvvm -Version 0.3.0
<PackageReference Include="RabstackQuery.Mvvm" Version="0.3.0" />
<PackageVersion Include="RabstackQuery.Mvvm" Version="0.3.0" />
<PackageReference Include="RabstackQuery.Mvvm" />
paket add RabstackQuery.Mvvm --version 0.3.0
#r "nuget: RabstackQuery.Mvvm, 0.3.0"
#:package RabstackQuery.Mvvm@0.3.0
#addin nuget:?package=RabstackQuery.Mvvm&version=0.3.0
#tool nuget:?package=RabstackQuery.Mvvm&version=0.3.0
RabStack Query MVVM
MVVM bindings for RabStack Query providing INotifyPropertyChanged ViewModels for MAUI, WPF, Avalonia, and other XAML frameworks. Built on CommunityToolkit.Mvvm source generators.
Installation
dotnet add package RabstackQuery.Mvvm
For Blazor apps, install RabstackQuery.Blazor instead, which includes this package and adds Blazor-specific component lifecycle management.
Quick Start
public partial class TodoListViewModel : ObservableObject, IDisposable
{
public QueryViewModel<List<Todo>> TodosQuery { get; }
public MutationViewModel<Todo, CreateTodoRequest> CreateTodo { get; }
public TodoListViewModel(QueryClient client, ITodoApi api)
{
TodosQuery = client.UseQuery(
["todos"],
async ctx => await api.GetTodosAsync(ctx.CancellationToken));
CreateTodo = client.UseMutation<Todo, CreateTodoRequest>(
async (request, _, ct) => await api.CreateTodoAsync(request, ct),
new MutationCallbacks<Todo, CreateTodoRequest>
{
OnSuccess = (_, _, _) => client.InvalidateQueries(["todos"])
});
}
public void Dispose()
{
TodosQuery.Dispose();
CreateTodo.Dispose();
}
}
XAML Binding
<StackLayout>
<ActivityIndicator IsRunning="{Binding TodosQuery.IsLoading}"
IsVisible="{Binding TodosQuery.IsLoading}" />
<Label Text="{Binding TodosQuery.Error.Message}"
IsVisible="{Binding TodosQuery.IsError}" TextColor="Red" />
<CollectionView ItemsSource="{Binding TodosQuery.Data}"
IsVisible="{Binding TodosQuery.IsSuccess}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding Title}" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Button Text="Refresh" Command="{Binding TodosQuery.RefetchCommand}" />
<Button Text="Add Todo" Command="{Binding CreateTodo.MutateCommand}" />
</StackLayout>
ViewModels
QueryViewModel<TData>
Wraps a QueryObserver with observable properties for data binding:
| Property | Type | Description |
|---|---|---|
Data |
TData? |
The last successfully resolved data |
Error |
Exception? |
The error if the query is in an error state |
Status |
QueryStatus |
Pending, Error, or Success |
FetchStatus |
FetchStatus |
Fetching, Paused, or Idle |
IsLoading |
bool |
First fetch in progress (no data yet) |
IsFetching |
bool |
Any fetch in progress (including background) |
IsError |
bool |
Query is in error state |
IsSuccess |
bool |
Query has data |
IsStale |
bool |
Cached data is past its stale time |
RefetchCommand |
IAsyncRelayCommand |
Manually trigger a refetch |
MutationViewModel<TData, TVariables>
Wraps a MutationObserver with observable properties and commands:
| Property | Type | Description |
|---|---|---|
Data |
TData? |
The last mutation result |
Error |
Exception? |
The error if the mutation failed |
Status |
MutationStatus |
Idle, Pending, Error, or Success |
IsIdle |
bool |
No mutation has been fired |
IsPending |
bool |
Mutation is in progress |
IsError |
bool |
Mutation failed |
IsSuccess |
bool |
Mutation succeeded |
MutateCommand |
IAsyncRelayCommand |
Fire the mutation (bindable) |
MutateCancelCommand |
ICommand |
Cancel a pending mutation |
Call InvokeAsync(variables) for awaitable mutation execution with error propagation.
QueryCollectionViewModel<TItem>
Wraps a query whose data is a collection, exposing an ObservableCollection<TItem> for efficient list binding:
var todosCollection = client.UseQueryCollection(
["todos"],
async ctx => await api.GetTodosAsync(ctx.CancellationToken),
(data, items) =>
{
items.Clear();
if (data is not null)
foreach (var todo in data) items.Add(todo);
});
// Bind to todosCollection.Items in XAML
Key Behaviors
- UI Thread Marshaling: All property changes are dispatched to
SynchronizationContext.Current, captured at construction time - Disposal Required: Always call
Dispose()on ViewModels to unsubscribe from query observers and prevent memory leaks - Command Error Handling:
RefetchCommandandMutateCommandswallow exceptions by default for safe fire-and-forget binding. UseInvokeAsyncwhen you need to handle errors
Documentation
See the GitHub repository for full documentation, architecture guide, and examples.
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- CommunityToolkit.Mvvm (>= 8.4.2)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.5)
- RabstackQuery (>= 0.3.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on RabstackQuery.Mvvm:
| Package | Downloads |
|---|---|
|
RabstackQuery.Blazor
Blazor component base class for RabStack Query — UseQuery/UseMutation hooks with automatic subscription, render coalescing, and disposal. |
GitHub repositories
This package is not used by any popular GitHub repositories.