Different types of bindings in Web Atoms for Xamarin.Forms
Akash Kava
Posted on April 4, 2020
Types of Bindings
Web Atoms offers two types of data bindings. JavaScript Data Binding and CLR Dta Binding. CLR Data Binding refers to existing Binding mechanisms offered in Xamarin/WPF in Xaml.
JavaScript Data Binding
Web Atoms framework provides Binding of JavaScript objects within JavaScript engine. This form of binding allows more features over CLR Data Binding. Data Binding in JavaScript allows you to rewrite custom expressions in JavaScript and you don't have to recompile your native app.
Pros of JavaScript Data Binding
- It can contain custom TypeScript expression
- You can write unit tests in JavaScript to cover conversions
- Smaller app size as all the code can live on server
- String resources can live on the server leading to smaller app size
- You can unit test your bindings with string resources in TypeScript
Cons of JavaScript Data Binding
- You cannot use CLR Value Converters
- You cannot use it in Control Templates
One Time JavaScript Binding
One time binding offers expression evaluation at later stage. As component is being built, not all properties are set at time of creation, order of property initialization is completely random.
<XF.Label
text={Bind.oneTime( () => this.viewModel.label )}
/>
You can also do the same by typing,
<XF.Label
text={this.viewModel.label}
/>
but it may fail as viewModel or label may not have been initialized.
One Way JavaScript Binding
One way binding offers expression evaluation whenever any of referenced properties are updated.
<XF.Label
text={Bind.oneWay(
() => `${this.viewModel.firstName} ${this.viewModel.lastName}`)}
/>
The above example offers simple concatenation of first name and last name whenever any of them is modified. Doing same in C# apart from simple string operations usually requires separate converter and binding expressions becomes very complex.
Data Binding in items scope
<XF.CollectionView>
<XF.CollectionView.itemTemplate>
<XF.DataTemplate>
<XF.Label
backgroundColor={Bind.oneWay(
(x) => this.selectedItem == x.data
? Colors.lightGreen
: Colors.white
)}
text={Bind.oneWay((x) => x.data.label)}
/>
</XF.DataTemplate>
</XF.CollectionView.itemTemplate>
</XF.CollectionView>
In above example, every item of CollectionView
receives an extra parameter x
that refers to UI Element in collection. And data
property of Element is the item in collection. Notice, that this expression can watch for changes in this.selectedItem
as well as x.data
(as x.data
changes while item template is reused). This successfully changes color when selected item is updated.
So Data Binding can easily works at nested scopes without having to create complex named relations which are required in CLR Data Binding.
So OneWay binding will watch for changes in any of
this.*.*....
expression and expression of typex.*.*....
wherex
is first parameter ofBind.oneWay
method.
Intellisense in Bind.oneWay
TypeScript with VS Code offers excellent intellisense, we can use it by declaring some interfaces.
const CustomerBinding = Bind.withData<ICustomer>;
<XF.CollectionView>
<XF.CollectionView.itemTemplate>
<XF.DataTemplate>
<XF.Label
backgroundColor={CustomerBinding.oneWay(
(x) => this.selectedItem == x.data
? Colors.lightGreen
: Colors.white
)}
text={CustomerBinding.oneWay((x) => /* error */x.data.label)}
/>
</XF.DataTemplate>
</XF.CollectionView.itemTemplate>
</XF.CollectionView>
In above example, we get an error that there is no label
on ICustomer
. While typing .
after data
will immediately display list of properties/fields that exists inside interface ICustomer
.
Two Way JavaScript Binding
Web Atoms offers two way data binding same as in CLR.
<XF.SearchBar
text={Bind.twoWays(() => this.viewModel.search)}
/>
CLR Data Binding
Though JavaScript Data Binding is sufficient in many ways, it lacks ability to provide control over Control Templates.
You can write ControlTemplate
in TSX, though you can use some JavaScript bindings but when you want to bind properties of Template Owner, you cannot do that with JavaScript.
But, You can create CLR DataBinding
object, and it will work exactly in same way. Let's look at the ControlTemplate
of AtomForm
which allows you to change look and field of each field.
<WA.AtomForm>
<WA.AtomForm.fieldStyle>
<XF.ControlTemplate>
<XF.Grid>
<XF.Grid.rowDefinitions>
<XF.RowDefinition height="Auto"/>
<XF.RowDefinition/>
<XF.RowDefinition height="Auto"/>
</XF.Grid.rowDefinitions>
<XF.Label
text={X.TemplateBinding("Label")}
textColor="Green"
/>
<XF.ContentPresenter
{ ... XF.Grid.row(1)}
/>
</XF.Grid>
</XF.ControlTemplate>
</WA.AtomForm.fieldStyle>
<WA.AtomField
label="Username:"
isRequired={true}
error={Bind.oneWay(() => this.viewModel.errorUsername)}>
<XF.Entry text={Bind.twoWays(() => this.viewModel.model.username)}/>
</WA.AtomField>
<WA.AtomField
label="Password"
isRequired={true}
error={Bind.oneWay(() => this.viewModel.errorPassword)}>
<XF.Entry
isPassword={true}
text={Bind.twoWays(() => this.viewModel.model.password)}
/>
</WA.AtomField>
<XF.Button
command={Bind.event((s, e) => this.viewModel.signup())}
text="Signup"/>
</WA.AtomForm>
In above example, you can see that X.TemplateBinding
allows you to bind Label
property of TemplateOwner
. Similarly you can use X.Binding
to bind CLR data objects.
Examples,
<XF.Label
text={X.Binding("path")}
You cannot use CLR DataBinding to bind JavaScript objects, this is not limitation but it is unnecessary step as watching expressions for changes in CLR is more time consuming and requires complex expressions. We may improve this in future based on performance analysis. Currently keeping all bindings JavaScript makes it easy to debug as you can easily create HTML component and test it in browser.
Pros of CLR Data Binding
- You can use them in
ControlTemplate
- You can reuse ValueConverters that exists in your C# code.
Cons of CLR Data Binding
- You cannot use them to bind JavaScript objects
- You cannot write unit test in JavaScript
- You have to recompile and republish your app if you make changes to value converters
Current Limitations
These are current limitations in TSX, however they will be added in future as we progress.
- No
Style
- No
Trigger
However, it seems that we can easily create StyleSheet
.
Xamarin Forms StyleSheet
// you can write style as template literal
const style = `
listview image {
height: 60;
width: 60;
}
stacklayout>image {
height: 200;
width: 200;
}
`;
<XF.Grid>
<XF.Grid.Resources>
<XF.StyleSheet source={style}/>
</XF.Grid.Resources>
</XF.Grid>
All Xamarin Components will automatically inherit whatever default Styles and StyleSheet you have added in
App.Resources
.So you can create a master style for your app and put it in your App. You can also dynamically load the content of style sheet for your app, so you don't have to recompile and republish your app.
Posted on April 4, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.