## ReactiveUI 4.0 Preview is live!
After coding some pretty interesting new features, as well as to update to the
latest released version of Rx (2.01), I am now releasing a preview release of
ReactiveUI 4.0. You can get the binaries one of two ways:
* `install-package reactiveui -pre` or `install-package reactiveui-winrt -pre`
* Download the Zip release [from
GitHub](
https://github.com/xpaulbettsx/ReactiveUI/downloads)
### How does this break backwards compatibility?
A few types have been renamed from 3.x (`IViewForViewModel` => `IViewFor`), a
few deprecated methods have been removed (CollectionExtensions), and the
biggest one is that NLog is now optional - if you want to use it, make sure to
install the `reactiveui-nlog` package (it comes by default in the reactiveui
metapackage)
### WhenAny now works with any object!
WhenAny and ObservableForProperty now work with *any* .NET object. The runtime
will detect what kind of object it is (DependencyObject, INPC, etc) and will
determine how to get notifications from it. Note that if you use WhenAny with
an object that doesn't notify (like a regular .NET object), it will warn you
on the logger that changes won't be reported. This framework is extensible as
well, so on MonoMac for example, notifications for NSObjects will be derived
using Key-Value Observing (KVO).
This means that the old `ObservableForDP` method is now deprecated - use
WhenAny instead.
### View Bindings: A Compelling Replacement for XAML bindings
There are currently two methods that are used in the XAML world for binding
Views to ViewModels. The original method, XAML Bindings (i.e. {Binding Foo}),
is quite flexible, but a frustrating aspect of it is that Bindings that are
incorrect, due to typos or other mistakes, don't generate errors - you only
see the error in the trace output. The Binding syntax can also get quite
verbose, and isn't always easy to verify because paths are relative to the
"nearest" DataContext set.
Caliburn Micro decided to take a different approach, with their
"Convention-Based Wireup" - this approach decides to automatically wire up
named controls with the properties of the same name (even being smart enough
to realize that the most "common" property of TextBox is the Text property).
While this approach is much more "wrist friendly", it suffers from the same
type of run-time failures: CM cannot know whether a binding should exist or
not.
ReactiveUI is presenting a new approach: wiring up controls via a declarative
syntax. This has a number of advantages:
* It's still wrist-friendly
* Bindings are clearly described in one place
* Bindings that are never valid (i.e. because the property name has changed)
break the build.
* This binding syntax isn't tied to Xaml - you can effectively use ReactiveUI
bindings with any UI framework with a bit of work, including Cocoa (MonoMac)
and GTK#.
Consider the following ViewModel, which is valid RxUI 3.x code as well:
public class MainPageViewModel : ReactiveObject
{
string _SomeText = "";
public string SomeText {
get { return _SomeText; }
set { this.RaiseAndSetIfChanged(x => x.SomeText, value); }
}
ObservableAsPropertyHelper<string> _FooMirror;
public string FooMirror {
get { return _FooMirror.Value; }
}
public ReactiveCommand Ok { get; protected set; }
public MainPageViewModel()
{
this.WhenAny(x => x.SomeText, x => x.Value)
.Select(x => "Foo" + x ?? "")
.ToProperty(this, x => x.FooMirror);
Ok = new ReactiveCommand();
}
}
In ReactiveUI 4.0, this is the way to wire up the View:
public partial class MainPage : Page, IViewFor<MainPageViewModel>
{
public MainPage()
{
ViewModel = new MainPageViewModel();
this.InitializeComponent();
// Connect the ViewModel's SomeText to the View's SomeText.Text
this.Bind(ViewModel, x => x.SomeText, x => x.SomeText.Text);
// Since the View half isn't specified here, it will default to the
// control with the same name, and use the most "reasonable"
// property, just like Caliburn Micro
this.OneWayBind(ViewModel, x => x.FooMirror);
// Ditto with Commands, find a Control named "Ok"
this.BindCommand(ViewModel, x => x.Ok);
}
object IViewFor.ViewModel {
get { return ViewModel; }
set { ViewModel = (MainPageViewModel) value; }
}
public MainPageViewModel ViewModel { get; set; }
}
This feature is a work in progress, and there are definitely some cases that
need to be smoothed out. However, I'd love feedback on whether this is useful
or not.
--
Paul Betts <
pa...@paulbetts.org>