Class QueryViewModel<TArgs, TData>
- Namespace
- DotNetQuery.Mvvm
- Assembly
- DotNetQuery.Mvvm.dll
An INotifyPropertyChanged view model wrapping an IQuery<TArgs, TData> for MVVM-based UI frameworks (MAUI, WPF, WinUI, UNO, Avalonia). Exposes the query state as bindable properties and marshals all change notifications onto the UI thread via an IUiDispatcher.
The view model holds a live subscription to State for its entire lifetime — this is what keeps the underlying cache entry retained and triggers deferred stale fetches. Dispose the view model when its page is torn down; a forgotten dispose keeps the cache entry alive indefinitely.
public class QueryViewModel<TArgs, TData> : BindableBase, INotifyPropertyChanged, IDisposable where TData : class
Type Parameters
TArgsThe type of the parameters passed to the fetcher.
TDataThe type of data returned by the query. Constrained to reference types.
- Inheritance
-
QueryViewModel<TArgs, TData>
- Implements
- Inherited Members
Constructors
QueryViewModel(IQueryClient, QueryOptions<TArgs, TData>, IUiDispatcher?)
Creates a new query observer via CreateQuery<TArgs, TData>(QueryOptions<TArgs, TData>) and wraps it. The view model owns the created query and disposes it in Dispose(). This is the recommended path for page view models that receive an IQueryClient through dependency injection.
public QueryViewModel(IQueryClient client, QueryOptions<TArgs, TData> options, IUiDispatcher? dispatcher = null)
Parameters
clientIQueryClientThe query client used to create the observer.
optionsQueryOptions<TArgs, TData>The query options.
dispatcherIUiDispatcherThe UI-thread dispatcher. When
null, Current is captured; construct the view model on the UI thread or pass a dispatcher explicitly.
QueryViewModel(IQuery<TArgs, TData>, IUiDispatcher?)
Wraps an existing query. The view model does not take ownership:
Dispose() releases only the view model's own state subscription,
and the caller remains responsible for disposing query.
public QueryViewModel(IQuery<TArgs, TData> query, IUiDispatcher? dispatcher = null)
Parameters
queryIQuery<TArgs, TData>The query to wrap.
dispatcherIUiDispatcherThe UI-thread dispatcher. When
null, Current is captured; construct the view model on the UI thread or pass a dispatcher explicitly.
Properties
CancelCommand
Triggers Cancel(). Enabled only while a fetch is in flight.
public ICommand CancelCommand { get; }
Property Value
CurrentState
The raw state snapshot, for bindings and converters that need the whole state.
public QueryState<TData> CurrentState { get; }
Property Value
- QueryState<TData>
Data
The data returned by the most recent successful fetch; null while fetching.
Bind to DisplayData to keep showing stale data during background re-fetches.
public TData? Data { get; }
Property Value
- TData
DisplayData
Data, falling back to LastData while a re-fetch is in progress —
the stale-while-revalidate binding target, mirroring the Blazor <Transition> component.
public TData? DisplayData { get; }
Property Value
- TData
Error
The exception from the most recent failed fetch. null when not in a failure state.
public Exception? Error { get; }
Property Value
HasData
true when Data is not null.
public bool HasData { get; }
Property Value
HasError
true when Error is not null.
public bool HasError { get; }
Property Value
IsFailure
true when the most recent fetch failed.
public bool IsFailure { get; }
Property Value
IsFetching
true while any fetch is in flight, including background re-fetches.
See IsLoading for the first-load-only variant.
public bool IsFetching { get; }
Property Value
IsIdle
true when the query is idle.
public bool IsIdle { get; }
Property Value
IsLoading
true only during the first load — fetching with no current or previous data to show.
Bind a full-page loading indicator to this and a subtle refresh indicator to
IsFetching.
public bool IsLoading { get; }
Property Value
IsSuccess
true when the most recent fetch succeeded.
public bool IsSuccess { get; }
Property Value
LastData
The data from the previous successful fetch, carried across fetches and failures.
public TData? LastData { get; }
Property Value
- TData
Query
The wrapped query — the escape hatch for members without a bindable counterpart (Invalidate(), PrefetchAsync(TArgs, CancellationToken), Select<TResult>(Func<TData, TResult>, IEqualityComparer<TResult>?), or direct Rx composition).
public IQuery<TArgs, TData> Query { get; }
Property Value
- IQuery<TArgs, TData>
RefetchCommand
Triggers Refetch(). Disabled while a fetch is in flight.
public ICommand RefetchCommand { get; }
Property Value
Status
The current lifecycle status of the query.
public QueryStatus Status { get; }
Property Value
Methods
Dispose()
Releases the view model's state subscription — which lets the cache entry's eviction clock start — and disposes the wrapped query if this view model created it.
public void Dispose()
Dispose(bool)
Releases resources. Override in derived view models to dispose additional state; always call the base implementation.
protected virtual void Dispose(bool disposing)
Parameters
SetArgs(TArgs)
Sets the args that drive the next fetch. When args change, the query switches to the cache entry for the newly derived key and triggers a fetch if the query is enabled.
public void SetArgs(TArgs args)
Parameters
argsTArgs
SetData(TData)
Directly writes data into the active cache entry as a success state,
bypassing any in-flight fetch. Stamps the entry as fresh so stale-time is respected
and an immediate re-fetch is not triggered.
Useful for applying optimistic updates before a mutation completes.
public void SetData(TData data)
Parameters
dataTData
SetEnabled(bool)
Enables or disables the query. When false, fetching is suspended even if the query is
invalidated or new args are pushed. Pass true to resume; the query will immediately
re-evaluate its active key and trigger a fetch if one is pending.
public void SetEnabled(bool enabled)
Parameters
enabledbool
Events
StateChanged
Raised on the UI thread after every PropertyChanged notification for an applied state. Use this — instead of a second raw subscription to Query's state — for page-specific work such as syncing an ObservableCollection<T> from DisplayData.
public event EventHandler? StateChanged