Namespace DotNetQuery.Mvvm
Classes
- BindableBase
A minimal INotifyPropertyChanged base class for view models. Deliberately not named
ObservableObjectto avoid ambiguity with MVVM toolkits that may coexist in consuming applications.
- InfiniteQueryViewModel<TArgs, TData, TPageParam>
An INotifyPropertyChanged view model wrapping an IInfiniteQuery<TArgs, TData, TPageParam> for MVVM-based UI frameworks (MAUI, WPF, WinUI, UNO, Avalonia). Exposes the paginated 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.
Pages are not flattened:
TDatais a single page and is not necessarily enumerable. Flatten in the owning page view model, e.g. by syncing an ObservableCollection<T> from Pages off StateChanged.
- MutationViewModel<TArgs, TData>
An INotifyPropertyChanged view model wrapping an IMutation<TArgs, TData> for MVVM-based UI frameworks (MAUI, WPF, WinUI, UNO, Avalonia). Exposes the mutation 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. Dispose the view model when its page is torn down.
Double-submit protection: ExecuteCommand, Execute(TArgs), and every command returned by ToCommand<TParam>(Func<TParam, TArgs>, Func<TParam, bool>?) read CurrentState directly — not the dispatcher-applied CurrentState below — before starting a run. That closes the gap between a click starting a run and the resulting state reaching this view model one dispatcher hop later, and it also disables these commands when a run was started directly on a shared Mutation by something other than this view model.
- ObservableCollectionExtensions
Reconciles an ObservableCollection<T> in place against a new source sequence — computing the minimal Move,
Insert,Remove, and (same-type overload only)Replaceoperations needed to match it, rather than clearing and re-adding. Clearing and re-adding drops whatever a bound control tracks by collection position — the selected row in a WPF/Avalonia list, for instance.
- QueryViewModelExtensions
Extension methods that wrap
DotNetQuery.Coretypes in view models, and marshal arbitrary observables onto the UI thread.
- QueryViewModel<TArgs, TData>
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.
- SynchronizationContextUiDispatcher
An IUiDispatcher backed by a SynchronizationContext. When the context is
null, actions are invoked inline on the calling thread — useful in unit tests and console applications that have no UI thread.
Interfaces
- IMutationCommand
An ICommand returned by ToCommand<TParam>(Func<TParam, TArgs>, Func<TParam, bool>?) and its parameterless overload. Exposes RaiseCanExecuteChanged() so a page view model can re-evaluate CanExecute(object) when an input outside the mutation's own state changes — for example a bound text field that the command's
canExecutepredicate reads.
- IUiDispatcher
Marshals work onto the UI thread so that INotifyPropertyChanged notifications are raised where bindings expect them.
The default implementation is SynchronizationContextUiDispatcher. Supply a platform-specific implementation to target the platform's dispatcher directly — e.g.
MainThread.BeginInvokeOnMainThread(MAUI),DispatcherQueue.TryEnqueue(WinUI/UNO),Dispatcher.BeginInvoke(WPF), orDispatcher.UIThread.Post(Avalonia).