Oh, hai!

Wow! It's been a while, but we have a juicy new release for you. We had to take some time to heal internally, to train and mentor the future generations of maintainers which are going to carry us forward. Additionally the .NET ecosystem changed underneath us, and we didn't have continuous integration setup. Let this be a lesson to anyone considering operating an open-source project that targets nine platforms. Have a roadmap and succession plan in place and never allow long-running branches, ever. Implement continuous integration and mature your release processes to the point where cutting a new release is as simple as pressing a button.
So what is ReactiveUI?
ReactiveUI is inspired by functional reactive programming and is the father of the ReactiveCocoa (Cocoa/Swift) framework. Internally we debate whether we are or are not a framework, as at its core the project is essentially a bunch of extension methods for the Reactive Extensions.
ReactiveUI was started seven years ago and is now old enough to attend grade school but unlike a teenager is extremely stable. ReactiveUI has matured over the years into a solid and fine choice for building your next application. Additionally, because the implementation is unopinionated migration from another framework to ReactiveUI is incredibly easy.. You can slide it in on a single ViewModel and then migrate as you become more comfortable. Avoid those costly rewrites.
When reading the code, you'll find that ReactiveUI is rather unopinionated in the implementation, but we have always held some beliefs which have been the basis and foundation of the project.
We believe that code is communication between people, that also happens to run on a computer. If you optimise for humans, then over a long time your project will end up better. Software should be understandable by other people; that is super important.
We believe that only the power of the Reactive Extensions allows you to express the idea around a feature in one readable place.

Think about your typical user interface? It's a mutable bag of sadness with code all over the place. Instead of telling a computer how to do its job, why not define what the computers job is and get out of its way? If that sounds odd, let us re-introduce you to Microsoft Excel.
Instead of doing the typical ViewModel isLoading = true/false mutable dance by toggling it on and off in different branches of your code. Why not express the condition in a single place using a Microsoft Excel expression - =SUM(A1: B2)?
Still not convinced?
- Why You Should Be Building Better Mobile Apps with Reactive Programming – Michael Stonis (Xamarin Univeristy Trainer/Eightbot)
- Awaiting for Rx: A Play in Four Acts - Anaïs Betts (Slack/GitHub)
- FRP In Practice: Taking a look at ReactiveUI/ReactiveCocoa by Anaïs Betts (Slack/GitHub)
Maybe you need to watch this insanely smart, and eccentric guy in a tie-dye t-shirt do maths on a whiteboard:
Async/await is the zombie plague. Liberate your codebase today.
ReactiveUI is used in production at GitHub, Slack, Microsoft and is supported by consultants from different companies from all around the world. It's used at our clients, we can't name names specifically, but we encourage our community to showcase where and how they have used ReactiveUI in their applications, some members have even gone as far as open-sourcing their app and sharing their entire codebase. You are of course under no obligation to share these insights (or code) with us but it is greatly appreciated by the project maintainers, and you'll usually get a retweet out of it.
Where are the examples?
We are working on it; this release was for us. Next release is for you. For now:
- Read https://docs.reactiveui.net/en/fundamentals/history.html
- Watch the guest lecture over at Xamarin Univeristy
- Watch this god damn amazing video series by Kent Boogaart (one of the core maintainers)
- Play with the Xamarin University lecture source code. (Xamarin Forms)
- Play with the GitHub for Windows Visual Studio source code. (WPF)
Rx is hard
No, it's not. Learning Rx is one of the best things you can do to improve yourself as a software engineer. Unit testing was hard, so was dependency injection at first. The principals you learn during your journey will forever change you and best of all the knowledge is implementation and language agnostic. We have designed ReactiveUI so you can slowly transition from an async/await codebase at a pace that feels comfortable to you.
Highlights
ReactiveCommand is Better
ReactiveCommand is completely rewritten again (sorry).
- interfaces are gone. Any use of
IReactiveCommandshould be replaced withReactiveCommand, possibly with type information (see below). - static creation methods have changed:
- execution logic is always required when calling
CreateXxxmethods, including synchronous commands (i.e. those created withCreate). So rather than callingCreateand then subscribing, you callCreateand pass in your execution logic right then and there. - for consistency, the execution logic is always provided as the first parameter. Other parameters (
canExecute,scheduler) are optional. CreateAsyncObservableis now calledCreateFromObservable.CreateAsyncTaskis now calledCreateFromTask.
- execution logic is always required when calling
- parameter types are formalized by
TParaminReactiveCommand<TParam, TResult>.- if your command takes a parameter, you no longer take an
objectand cast it. Instead, you explicitly specify the parameter type when creating the command (of course, you can still chooseobjectas yourTParamif that makes sense, perhaps as an intermediary migration step).
- if your command takes a parameter, you no longer take an
ICommandis now implemented explicitly. As a result:- the
Executeexposed byReactiveCommandis reactive (it returnsIObservable<TResult>). It is therefore lazy and won't do anything unless something subscribes to it. CanExecuteObservableis now calledCanExecute.
- the
- observables such as
CanExecuteandIsExecutingare now behavioral. That is, they will always provide the current value to new subscribers. RoutingStatehas been updated to use the new implementation. Consequently, any use of its commands will be affected per the above.- the
ToCommandextension method has been removed. This was a simple convenience to take anIObservable<bool>and use it as thecanExecutepipeline for a new command. If you're usingToCommand, you can just replace it with a call to one of the creation methods onReactiveCommand.
Old:
var canExecute = ...;
var someCommand = ReactiveCommand.Create(canExecute);
someCommand.Subscribe(x => /* execution logic */);
var someAsyncCommand1 = ReactiveCommand.CreateAsyncObservable(canExecute, someObservableMethod);
var someAsyncCommand2 = ReactiveCommand.CreateAsyncTask(canExecute, someTaskMethod);
someCommand.Execute();
New:
var canExecute = ...;
var someCommand = ReactiveCommand.Create(() => /* execution logic */);
var someAsyncCommand1 = ReactiveCommand.CreateFromObservable(someObservableMethod, canExecute);
var someAsyncCommand2 = ReactiveCommand.CreateFromTask(someTaskMethod, canExecute);
someCommand.Execute().Subscribe();
For more details, please see the extensive documentation on this topic.
Note To enable you to ease into the migration, all previous types are available under the
ReactiveUI.Legacynamespace. Note, however, that there is no legacy version ofRoutingState, so any code you have that interacts with its command may require minor updates.
Interactions are New and Exciting
UserError has been generalized and re-imagined. We call it interactions, and we think you'll like it. We did this in part because people were feeling icky using UserError for non-error scenarios. Basically, we realized that people need a general mechanism via which a view model can ask a question, and wait for the answer. It doesn't have to be an error - we're not that pessimistic! You could be asking to confirm a file deletion, or maybe how the weather is out there in the analog world.
Migrating from UserError to the interactions infrastructure is not really a case of one-for-one substitution. But here are some tips to get you started:
- read through the documentation first.
- decide whether you need shared interactions and, if so, define them in an appropriate place for your application (often just a static class).
- for any non-shared interactions, have your view model create an instance of the interaction and expose it via a property.
- typically you want the corresponding view to handle interactions by calling one of the
RegisterHandlermethods on the interaction exposed by the view model. - the view model can call
Handleon the interaction, passing in an input value. - Recovery commands are no longer a built-in thing. If you need such a mechanism for your interactions, you are encouraged to write an appropriate class and use it as the input for your interaction.
Note To enable you to ease into the migration, all previous types are available under the
ReactiveUI.Legacynamespace.
ToProperty is now eager by default
In previous ReactiveUI versions, ToProperty was lazy. That is, it would have no effect unless something was "pulling" on the target property. This was for performance reasons, as you may have properties that are expensive to resolve, but only used in specific scenarios.
Whilst this was good for performance, it was often confusing and contrary to expectations. Therefore, ToProperty is no longer lazy - it immediately subscribes to ensure the property's value reflects the given observable pipeline. However, the original lazy behavior can be obtained by passing in true to the deferSubscription parameter.
Automation galore
A mountain of effort has gone into automating ReactiveUI's build and deployment infrastructure (thanks @ghuntley!). Using tools such as Cake, AppVeyor, and gitversion, we now have a very compelling automation story. This is no mean feat, especially considering the vast array of platforms on which ReactiveUI runs, and must therefore be built.
The end goal here is to get you, the community, new versions of ReactiveUI more rapidly and seamlessly.
Details
As part of this release we had 113 issues closed.
All Platforms
- #1189 Add
WhenAnyObservableoverloads that combine latest via a given selector - #1161 Remove
BindCommandimplementation takingFunc<TParam> - #1158 Throw
UnhandledErrorExceptionwhen a thrown exception goes unhandled (rather than justException) - #1157 Fix
InvokeCommandto respect the command's execution window - #1091 Add
WhenActivatedoverload that takes aCompositeDisposable, as well as aDisposeWithextension method - #971 #1035 #1054 #1085 #1088 Overhaul reactive commands
- #1084 Enhance
ToPropertyto work with indexers - #1082 Add scheduling support to
RoutingState - #1079 Add
ActivatedandDeactivatedobservables toViewModelActivator - #1061
ToPropertyis no longer lazy by default - #964 #1055 #1181 Add interactions feature
- #1052 Add
Bindoverloads that convert viaFuncs - #1028 Improve
CreateCollectionoverloads - #1021 Generalize auto-persistence helpers to work against
IReactiveCollection<T> - #1018
BindTonow throws a helpful exception when attempting to bind tonull - #1015 Enhance the default view locator to resolve views when the VM is abstracted as an interface
- #1013 Add auto-registration feature for views within a given assembly
- #1012 Add scheduler parameter to
CreateCollection - #977 Add
WhenNavigatedToObservablemethod, telling you whenever a given view model is on top of the navigation stack - #962 Fix a race condition in
ObservableAsPropertyHelper - #938 Don't automatically create a
DataTemplateif theDisplayMemberPathof anItemsControlis set - #936 Ensure
ObservableAsPropertyHelperprovides the initial value immediately - #926 Remove potentially expensive hash calculation from
ReactiveList - #914 Remove
ViewContractAttribute - #913 Remove
fallbackValuefrom binding methods - #875 Relax generic constraints on
ToPropertyfromReactiveObjecttoIReactiveObject - #943 Add
ReactiveUserControlto relevant XAML platforms - #935 Add
XmlnsDefinitionAttributefor those XAML platforms that support it - #879 Add
ViewContractproperty toViewModelViewHostfor XAML platforms - #1149 Set nuspec dependency to == (exact) version as that is being built
- #1142 Fix Splat dependency
- #1110 Fix
WaitForSchedulerexception handling
Events Generator
- #1151 reactiveui-events now targets UWP 10.0.14393.0 (aka anniversary edition)
- #1056 eventbuilder.exe is now xplat and always uses the latest SDK's
- #1187 Ignore CS[1591,0618,0105,0672] because that code is generated
Windows Phone, Store and Universal
- #1192 Fixed ReactiveUI to install into a library targeting WPA81 (Profile111)
- #1174 Retired Windows Phone Silverlight
- #1099 Changed
LaunchActivatedEventArgstoIActivatedEventArgs - #1045 Add Universal Windows Platform (UWP) support
- #940 Update platform UAP 10069 -> UWP 10240, add Events and Testing projects
Xamarin Android
- #1186 Android timepicker now uses
Hour/Minuteinstead ofCurrentHour/CurrentMinute - #1144 Small bug fixes to
ReactiveRecyclerViewAdapterandViewHolder - #1105 Add
ReactiveAppCompatActivity - #1095 Add
AsObservablewhenISubjectis returned asIObservable - #1067 Add Android reactive preferences
- #1059 Add Rx implementation of the Android shared preferences changed
- #1058 Add Rx implementation of the Android USB permission request
- #1057 Add Rx implementation of the Android service bind
- #1044 Resolve an issue building android support project
- #985 Add
serializer.Serialize(st, state);intoSaveState - #982 Add a basic reactive adapter for the Android
RecyclerView - #939 Add a reactive version of the
Android.Support.V4.DialogFragmentclass - #885 Add a
ControlFetcherMixinfor the Android Support library
Xamarin Forms
- #1160 Use non-generic
BindableProperty.Create, since the generic overloads are deprecated - #952 #1115 Add support for view activation
- #942 #1074 #1071 #986 Lots of routing fixes and improvements
- #1032 Add reactive pages
- #921 Add reactive cells
- #953 Upgrade Xamarin Forms dependency
- #951 Throw a useful exception from
ViewModelViewHostif the view is of the wrong type - #950 Use
ContentViewas base class forViewModelViewHost - #919 Fix
ViewModelViewHostbug where collection is modified whilst being enumerated - #861 Retarget ReactiveUI.Xamforms to Profile259
- #1153 Update reactiveui-xamforms nuspec dependency from v2.1.0.6529 to v2.3.1.114
- #1152 Upgrade reactiveui-core for Xamarin.Forms from v2.2.0.31 to v2.3.1.114
- #1150 Upgrade reactiveui-events for Xamarin.Forms from v2.2.0.31 to v2.3.1.114
- #1196 Resolve a crash when using
ViewModelViewHostwith Xamarin Forms
Xamarin iOS
- #1182 Use
ViewWillAppearfor iOS activation (notViewDidAppear) - #1176 Migrate reactiveui-testing from Monotouch to Xamarin.iOS
- #1087 Make
ReactiveNavigationControlleractivatable - #1086 Fix various
RoutedViewHostissues - #927 Rewrite
CommonReactiveSourceto be reactive and fix numerous bugs - #917 Add
ReactiveSplitViewController - #874 Make iOS
ViewModelViewHostan actual view controller - #873 Fix a
CommonReactiveSourcerace condition by ensuring that batched changes result inBeginUpdatescall ASAP - #1177 Fix code generation of events with iOS 10
Xamarin Mac
- #1185 Use Xamarin.Mac framework for reactiveui/reactiveui-testing/microsoft-reactive-testing
- #1175 Xamarin.Mac (unified) now compiles on windows
- #1022 Add
ViewAttributesto Xamarin.Mac projects - #916 Fix
ViewModelViewHoston Mac - #887 Changed output to Xamarin.Mac20 to reflect reality and added .nuspec
Housekeeping
- #1188 Upload .dll artefacts to AppVeyor on successful build
- #1179 Run unit tests as part of continuous integration pipeline
- #1178 Resolved an issue with continuous integration pipeline
- #1148 Bootstrapper now downloads/installs Android API level 24
- #1140 Add GitHub issue/PR templates
- #1128 Enable strict mode (fail the build on any powershell error)
- #1092 Continuous integration and pre-release builds for v7
- #1010 Compiler warnings for events disabled to reduce CI log spam
Documentation
Where to get it
You can download this release from nuget.org
