Compiled bindings with {x:Bind}
are an awesome feature of Universal Windows Platform XAML. Instead of using reflection, the data bindings are evaluated at compile-time, which not only shields us against unintended typos but gives significant performance boost at runtime as well. The only “annoyance” is that opposed to classic {Binding}
it has a different default setting for its mode – instead of OneWay
it uses OneTime
. While this also improves performance for unchanging data, it is deceptively easy to forget to explicitly set OneWay
where required. Furthermore, when we are showing multiple current values from a changing data source, it is a bit verbose to have to add the Mode
property to every x:Bind
. Luckily, there is a remedy for that!
x:DefaultBindMode
In SDK version 14393, x:DefaultBindMode
was introduced. This neat little feature allows us to set the default {x:Bind}
mode for an element and all its children unless explicitly overridden.
Suppose we have the following XAML:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Grid> | |
<TextBlock Text="{x:Bind ViewModel.Symbol}" /> | |
<TextBlock Text="{x:Bind ViewModel.Price}" /> | |
<TextBlock Text="{x:Bind ViewModel.PriceChange}" /> | |
</Grid> |
Because mode has not been explicitly specified for either expression, it defaults to OneTime
and after the values are evaluated for the first time, they no longer track further changes. Now, let’s change that using x:DefaultBindMode
:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Grid x:DefaultBindMode="OneWay"> | |
<TextBlock Text="{x:Bind ViewModel.Symbol}" /> | |
<TextBlock Text="{x:Bind ViewModel.Price}" /> | |
<TextBlock Text="{x:Bind ViewModel.PriceChange}" /> | |
</Grid> |
Just like that, all three TextBlock
elements will update their text anytime the bound property changes.
To make our life even easier, if we know most data bindings will be dynamic, we can even set the x:DefaultBindMode
at the root element level:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Page | |
… | |
x:DefaultBindMode="OneWay"> |
Of course it is easy to override the setting whenever necessary:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<StackPanel x:DefaultBindMode="OneWay"> | |
<TextBox Text="{x:Bind ViewModel.Name, Mode=TwoWay}" /> | |
<TextBlock Text="{x:Bind ViewModel.Name}" /> | |
</StackPanel> |
While the TextBlock
will use OneWay
update mode, TextBox
uses TwoWay
instead.
A great use for DefaultBindMode
is when building input forms. We can just set the default to TwoWay
and no longer need to remember it:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<StackPanel x:DefaultBindMode="TwoWay"> | |
<TextBox Header="First name" Text="{x:Bind ViewModel.FirstName}" /> | |
<TextBox Header="Last name" Text="{x:Bind ViewModel.LastName}" /> | |
<CheckBox Content="Is subscribed" IsChecked="{x:Bind ViewModel.IsSubscribed}" /> | |
</StackPanel> |
x:DefaultBindMode
is a tiny but lovely XAML feature, which makes working with x:Bind
so much more pleasant!
We’re waiting for your PR to support it on Uno 😉
👩💻
I am looking forward to it anxiously.