Thursday, 25 October 2018

Xamarin.Forms Compiled Bindings FAQ

We recently announced compiled bindings for Xamarin.Forms. Bindings aren’t cost efficient because they are resolved at runtime using reflection. In some scenarios this can introduce a performance hit. In addition, there isn’t any compile-time validation of binding expressions, and so invalid bindings aren’t detected until runtime.

Compiled bindings aim to improve data binding performance in Xamarin.Forms applications by resolving binding expressions at compile-time, rather than runtime. As well as providing compile-time validation of binding expressions, more importantly they eliminate the reflection used to resolve the bindings at runtime.

How compiled bindings are used is documented here. Rather than repeat all that information, I thought it might be useful to provide a high-level FAQ about them. So here goes.

How do compiled bindings work?

When you create a binding in Xamarin.Forms XAML, it’s accomplished with the Binding markup extension, which in turn creates a Binding, which in turn inherits from the BindingBase class. This is what we call a classic binding. When you create a compiled binding in Xamarin.Forms XAML, it’s accomplished with the Binding markup extension, which in turn creates a TypedBinding, which in turn inherits from the TypedBindingBase class, which in turn inherits from the BindingBase class. This inheritance hierarchy is shown in the following simplified class diagram:


Rather than accept a binding path (like the Binding constructor does), the TypedBinding constructor takes a Func that gets the value from the source, an Action that sets it, and a list of property changed handlers. XAMLC then takes the binding path from your XAML and uses it to create the TypedBinding for you. Also, the Binding markup extension knows whether to return a Binding or a TypedBinding.

Are compiled bindings more performant than classic bindings?

Yes. Classic bindings use reflection. Compiled bindings eliminate this reflection, replacing it with a Func to get data, an Action to set data, and a list of handlers for property change notification.

How much more performant are compiled bindings than classic bindings?

How long is a piece of string? Ultimately it depends on the platform, OS, and the device but internal testing has shown that compiled bindings can be resolved 8-20 times quicker than classic bindings. See Performance for more information.

Which version of Xamarin.Forms supports compiled bindings?

Compiled bindings have been present in Xamarin.Forms for a while, but at the time of writing I’d recommend using Xamarin.Forms 3.3 as more compiled binding scenarios are supported in this release.

Can you create TypedBinding objects in code?

Technically yes, but it's not recommended for the following reasons:

  1. While the TypedBinding type is public, it's not intended to be used by app developers. It's public purely because it's consumed by the IL generated by XAMLC. It should be thought of as internal.
  2. Consequently, the TypedBinding type deliberately won't appear in your IDE intelligence.
  3. Why would you want to? You end writing code like this:

var binding = new TypedBinding<ComplexMockViewModel, string>( cmvm => cmvm.Model.Model.Text, (cmvm, s) => cmvm.Model.Model.Text = s, new [] { new Tuple<Func<ComplexMockViewModel, object>, string>(cmvm=>cmvm, "Model"), new Tuple<Func<ComplexMockViewModel, object>, string>(cmvm=>cmvm.Model, "Model"), new Tuple<Func<ComplexMockViewModel, object>, string>(cmvm=>cmvm.Model.Model, "Text") }) { Mode = BindingMode.OneWay };

Why do compiled bindings require XAMLC?

XAMLC will take the binding path from your XAML binding expression and use it to create the TypedBinding for you. Thus avoiding writing code like above.

Do compiled bindings work when the BindingContext is set in code, rather than XAML?


Should I replace my classic bindings with compiled bindings?

It’s up to you. If you don’t have a performance problem with your classic bindings, why bother replacing them? On the other hand, there’s no harm in replacing classic bindings with compiled bindings.

Really, the key scenario for replacing classic bindings with compiled bindings is where you’ve identified a performance problem. Maybe you have a performance problem in a ListView on Android. Try switching to compiled bindings there to see if it helps.

Can every classic binding be replaced with a compiled binding?

No. Compiled bindings are currently disabled for any binding expressions that define the Source property. This is because the Source property is always set using the x:Reference markup extension, which can’t currently be resolved at compile time.

No comments:

Post a Comment