Operators in ReactiveUI¶
An operator is a method that makes a new stream from an existing one: it filters values, changes them, combines streams, or waits. You chain operators the way you chain LINQ methods. ReactiveUI adds a few of its own that connect streams to properties and commands.
The examples use these namespaces:
using ReactiveUI;
using ReactiveUI.Primitives;
using ReactiveUI.Primitives.Signals;
Your first pipeline¶
A search box should run a search once the user stops typing, and only for two characters or more.
public sealed class SearchViewModel : ReactiveObject
{
private string _searchText = "";
public SearchViewModel()
{
Search = ReactiveCommand.Create<string>(text => Console.WriteLine($"searching for {text}"));
this.WhenAnyValue(x => x.SearchText)
.Calm(TimeSpan.FromMilliseconds(300))
.Where(text => text.Length >= 2)
.InvokeCommand(Search);
}
public string SearchText { get => _searchText; set => this.RaiseAndSetIfChanged(ref _searchText, value); }
public ReactiveCommand<string, RxVoid> Search { get; }
}
1. Start from a property. WhenAnyValue sends SearchText each time it changes.
2. Wait for a pause. Calm sends a value only after 300 ms pass with no newer one.
3. Filter. Where drops text shorter than two characters.
4. Run the command. InvokeCommand executes Search with each value, when the command can run.
var search = new SearchViewModel();
search.SearchText = "rx";
search.SearchText = "reactiveui";
Output, 300 ms later:
searching for reactiveui
rx never reached the command: reactiveui replaced it within 300 ms.
ReactiveUI's operators¶
ToProperty¶
ToProperty turns a stream into a read-only property. It stores the latest value in an
ObservableAsPropertyHelper<T> and raises PropertyChanged for the property each time the value changes.
public sealed class NameViewModel : ReactiveObject
{
private readonly ObservableAsPropertyHelper<string> _fullName;
private string _firstName = "";
private string _lastName = "";
public NameViewModel() =>
_fullName = this.WhenAnyValue(x => x.FirstName, x => x.LastName, (first, last) => $"{first} {last}")
.ToProperty(this, x => x.FullName);
public string FirstName { get => _firstName; set => this.RaiseAndSetIfChanged(ref _firstName, value); }
public string LastName { get => _lastName; set => this.RaiseAndSetIfChanged(ref _lastName, value); }
public string FullName => _fullName.Value;
}
var named = new NameViewModel();
named.FirstName = "Grace";
named.LastName = "Hopper";
Console.WriteLine(named.FullName);
Output:
Grace Hopper
ReactiveUI.Binding's source generator can write the helper field and the property body for you. Mark a partial
property [ObservableAsProperty]. See Properties backed by observables.
InvokeCommand¶
InvokeCommand executes a command with each value from a stream, and skips values that arrive while the command
cannot run. Your first pipeline shows it. See commands.
WhenAnyValue and WhenAnyObservable¶
WhenAnyValue makes a stream from properties. WhenAnyObservable follows a property that itself holds a stream, such
as a command on a child view model. See WhenAny.
Every other operator¶
The rest come from ReactiveUI.Primitives. Each page covers every operator in its group, with an example.
| You want to | Operators | Page |
|---|---|---|
| Change each value, or flatten a stream of streams | Select, SelectMany, Fold, SwitchTo | Transformation |
| Drop values you do not want | Where, Unique, Take, Skip, TakeUntil | Filtering |
| Join streams | SyncLatest, Blend, Zip, Concat, Race | Combination |
| Wait, batch, sample or time out | Calm, Shift, Buffer, Probe, Expire | Time |
| Recover from a failure | Recover, Retry, Reattempt, Finally | Error handling |
| Reduce a stream to one answer | Aggregate, Count, Any, ToList | Aggregation and results |
| Peek at values, or choose a thread | Tap, WitnessOn, Serialize | Utility |
| Share one run between subscribers | Publish, Replay | Sharing one subscription |
For a search that also cancels a stale request, see a search box, two ways.
Related topics¶
- Streams in ReactiveUI
- Best practices
- ReactiveUI.Primitives and System.Reactive, for the System.Reactive names of these operators.