x:DefaultBindMode in Uno Platform & how it's implemented

Xamarin Uno Platform WinUI XAML

4 years ago

Last week I published an article about the x:DefaultBindMode feature in UWP XAML. Uno Platform, the cross-platform UWP/WinUI bridge for Android, iOS, and WebAssembly, was at that time missing the feature. What happened next, was astounding. In just over a day, the feature was not only implemented but also merged (along with several additional improvements like BindBack!) and available in the latest prerelease package on NuGet. Just wow.

Uno Platform

Example on WASM

Taking one of the code samples from my previous article:

It now just works as expected on WebAssembly running Uno Platform – TextBlock uses OneWay binding, while TextBox explicitly overrides this with TwoWay. The same on all other Uno Platform targets.

x:DefaultBindMode in action on WebAssembly!

x:DefaultBindMode in action on WebAssembly!

How did they do this?

I thought it would be interesting to look into how the Uno Platform team achieved this magically quick implementation of the feature. The whole feature was implemented in the XamlFileGenerator class, which generates C# code from XAML. The x:DefaultBindMode feature works as a "scope," meaning the declared mode applies to an element and all its children unless overridden somewhere further down the tree. As the XAML file is parsed in a depth-first manner, the most appropriate data structure to maintain the currently "active" bind mode is a LIFO (Last-In-First-Out) data structure like a stack. And that is what Uno Platform uses to maintain the feature's state:

Notice the stack is initialized with OneTime – this matches the UWP's default x:Bind mode. So unless x:DefaultBindMode is used in the XAML file, OneTime is the fallback. How do we push a new "default mode" in the stack? That's where the TrySetDefaultBindMode method comes in:

First, the code retrieves the DefaultBindMode attribute from the element's XAML definition. If this is not defined, the method short-circuits and returns null. If the bind mode was defined, it is validated against the list of known values (IsValid) method. For a valid DefaultBindMode value, we need to push it onto the stack to start a new scope. The method then returns a DisposableAction instance, which implements IDisposable and makes sure to execute the passed in lambda when it is disposed of. And in this case, it pops the top value off the stack to end the current scope. This greatly aids the readability of the code, as it really signifies the fact that the method creates a new scope when used with the using block:

Note that in case TrySetDefaultBindMode evaluates to a null (for the case when DefaultBindMode is not set), using statement just ignores it (and does not attempt to call Dispose() on null at the end). Finally, retrieving the currently set mode is a simple Peek of the top of the stack:

The GetDefaultBindMode() method is used, when the x:Bind evaluation function is constructed:

Succinctly said, when the x:Bind explicitly states a Mode, it takes precedence. Otherwise the currently active DefaultBindMode is applied. That's all there's to it! As we can see, the feature was implemented very elegantly, and thanks to Uno Platform, we really have #WinUIEverywhere!