Back

BUILD 2015 session recap: Boost your app's performance through new enhancements to XAML Data Binding

Session url: http://channel9.msdn.com/Events/Build/2015/3-635

Objective: Know why you want to use compiled binding, how to use it and and how it works.

Compiled binding

The heavy lifting is done at build time rather than at runtime by converting bindings to generated code behind. This results in a major perfomance and memory increase at runtime.

Binding performance graph

How to

  • Replace {Binding .. } with {x:Bind }
  • Strongly typed: context is Page/User control.
  • Mode = OneTime is default (for performance), which is cheaper than OneWay.

Note that since these bindings are compiled, element binding is changed and is strongly typed as well.

Visibility="{x:Bind MyGrid.Children[0].Visibility}"

Data conversion is done in multiple ways:

  • Object to string: use the .ToString() method 
  • Value from string: uses the XAML parser’s logic
  • Converters are required when it’s not assignable in code (e.g. Boolean to Enum)

One way binding listens to:

  • INotifyPropertyChanged
  • DependencyProperty
  • INotifyCollectionChanged / IObservableVector

Two way binding:

  • DependencyProperty
  • TextBox is a special case: wait for LostFocus to occur (like it was in Windows 8.1 already)

Data templates have always been a place where we use bindings a lot and where it can get complex. Since x:Bind is strongly typed and we need to know the type, this can be added on the DataTemplate root.

<DataTemplate x:DataType="model:IEmployee">
    <Grid>
        <TextBlock Text="{x:Bind Name}"/>
    </Grid>
</DataTemplate>

We usually move reusable data templates to a resource dictionary. But since x:Bind compiles at build time, we need a place to dump the code for resource dictionaries with the new bindings. Therefor this resource dictionary:

  • Need to have a class.
  • Need to have code behind with InitializeComponent.
  • Need to be loaded using their type in the MergedDictionaries tag.
<ResourceDictionary.MergedDictionaries>
    <!-- with binding -->
    <local:MyTemplates/>
    <!-- without binding -->
    <ResourceDictionary Source="filename" />
</ResourceDictionary.MergedDictionaries>

Progressive rendering for list items

Another painful point in data binding was the performance of large lists. Windows 8.1 brought the ContainerContentChanging event to enable progressive rendering, but this required code to update the template.

In Windows 10 x:Phase enables declarative support phased rendering, with the default phase being 0 and everything higher being rendered afterwards.

<DataTemplate x:DataType="model:FileItem">
  <Grid Width="200" Height="80">
    <TextBlock Text="{x:Bind DisplayName}" />
    <TextBlock Text="{x:Bind prettyDate}" x:Phase="1"/>
  </Grid>
</DataTemplate>

Some best practices / guidance:

  • Limit the amount of phases to keep the performance improvement.
  • You can skip phase numbers (and plug in between them later on).

Event binding

A common practive when using MVVM is to use ICommand/EventToCommand to bring your events back to your view model. Now you can simply bind your event (e.g. Click) to a method on your datacontext (view model). The signature needs to apply to:

  • Have no parameters.
  • Or match the event parameters (can be base types).
  • Overloading is not supported.

It doesn’t cover CommandParameter or ICommand.CanExecute though.

Binding lifecycle

  • Bindings.Initialize() will initialize bindings.
  • Use Bindings.Update() for async data, can be used to update OneTime bindings.
  • Use Bindngs.StopTracking() to pause tracking (in case of a lot of changes), Bindings.Update() will both update and resume the tracking.
  • For lists: consider INCC update of the item instead of INPC for property.

Some remarks

  • x:Bind uses the page/control as context, so you can use the element name for Element bindings.
  • TemplatedParent is not supported, use TemplateBinding here.
  • Binding context is fixed and can’t be changed for subelements (unless on a template), so use the long path or create a property to bind to.
  • Duck typing: use a base class or interface for the shared properties.
  • No support for dictionary graphs (like JSON).
  • No possibility to add/remove bindings at runtime.
  • Can’t be used in a style for setters, but can be used in a DataTemplate in that style.

Extra

You can find a full sample on binding in the Windows Universal Samples on GitHub.

Licensed under CC BY-NC-SA 4.0; code samples licensed under MIT.
comments powered by Disqus
Built with Hugo - Based on Theme Stack designed by Jimmy