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.
Example on WASM
Taking one of the code samples from my previous article:
It now just works as expected on WebAssembly running Uno Platform –
OneWay binding, while
TextBox explicitly overrides this with
TwoWay. The same on all other Uno Platform targets.
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.
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 (
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
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
null at the end).
Finally, retrieving the currently set mode is a simple
Peek of the top of the stack:
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!