Boilerplate Code¶
A view model repeats the same few shapes. Each read-write property needs a backing field and a setter that calls
RaiseAndSetIfChanged. Each output property needs an ObservableAsPropertyHelper<T> field, a getter that returns
its Value, and a ToProperty call. Each command needs a property and a ReactiveCommand.Create call.
View Models shows each shape written by hand.
ReactiveUI brings two source generators that write these shapes for you. A source generator is a compiler add-on that writes C# code while your project builds. You install nothing extra: every project that references a ReactiveUI package gets both.
Let the generators write a view model¶
- Make the class
partial. The generators add their code to the other part of the class. - Add
using ReactiveUI.SourceGenerators;to each file that uses[Reactive]or[ReactiveCommand]. ReactiveUI adds no globalusingfor that namespace. - Mark each read-write property
[Reactive]. Declare it as apartialproperty with an emptygetandset. - Mark each command method
[ReactiveCommand]. The generator writes a property named after the method, followed byCommand. - Mark each output property
[ObservableAsProperty]. Declare it as apartialget-only property, and assign the generated_{name}Helperfield withToPropertyin the constructor. - Build. The generators write the property bodies, the fields and the commands.
ReactiveUI.SourceGenerators walks through a full view model built this way.
Which attribute writes which shape¶
| Shape you would write by hand | Attribute | Comes from | Reference |
|---|---|---|---|
A read-write property that calls RaiseAndSetIfChanged | [Reactive] | ReactiveUI.SourceGenerators | Properties with [Reactive] |
A ReactiveCommand property that wraps a method | [ReactiveCommand] | ReactiveUI.SourceGenerators | Commands with [ReactiveCommand] |
An output property backed by ObservableAsPropertyHelper<T> | [ObservableAsProperty] | ReactiveUI.Binding | Declare the property with an attribute |
A property that follows an ObservableCollection<T> | [ReactiveCollection] | ReactiveUI.SourceGenerators | Collections |
The IReactiveObject members on a class with another base class | [IReactiveObject] | ReactiveUI.SourceGenerators | Classes that cannot derive from ReactiveObject |
Use a [Reactive] partial property, not a [Reactive] field, for any property you pass to WhenAnyValue.
ReactiveUI.Binding cannot see a property generated from a field, so WhenAnyValue on it throws at run time.
Analyzer messages¶
The ReactiveUI.SourceGenerators analyzers report an RXUISG warning or error when they cannot handle an attribute.
Analyzer messages lists each one and what it means.
A project that references ReactiveUI.SourceGenerators itself, at a version older than 4.0.0, fails to restore with
error NU1605. Remove that PackageReference, or set it to 4.0.0 or later.