Binding from XAML works on the whole the same as in other XAML frameworks: you use the {Binding}
markup extension. Avalonia does have some extra syntacic niceties however. Here's an overview of
what you can currently do in Avalonia:
By default a binding binds to a property on the DataContext, e.g.:
<!-- Binds to the tb.DataContext.Name property -->
<TextBlock Name="tb" Text="{Binding Name}"/>
<!-- Which is the same as ('Path' is optional) -->
<TextBlock Name="tb" Text="{Binding Path=Name}"/>
An empty binding binds to DataContext itself
<!-- Binds to the tb.DataContext property -->
<TextBlock Name="tb" Text="{Binding}"/>
<!-- Which is the same as -->
<TextBlock Name="tb" Text="{Binding .}"/>
This usage is identical to WPF/UWP etc.
You can also specify a binding Mode:
<!-- Bind two-way to the property (although this is actually the default binding mode for
TextBox.Text) so strictly speaking it's unnecessary here) -->
<TextBox Name="tb" Text="{Binding Name, Mode=TwoWay}"/>
This usage is identical to WPF/UWP etc.
When you're creating a control template and you want to bind to the templated parent you can use:
<TextBlock Name="tb" Text="{TemplateBinding Caption}"/>
<!-- Which is short for -->
<TextBlock Name="tb" Text="{Binding Caption, RelativeSource={RelativeSource TemplatedParent}}"/>
This usage is identical to WPF/UWP etc.
If you want to bind to a property on another (named) control, you can use ElementName as in
WPF/UWP:
<!-- Binds to the Tag property of a control named "other" -->
<TextBlock Text="{Binding Tag, ElementName=other}"/>
However Avalonia also introduces a shorthand syntax for this:
<TextBlock Text="{Binding #other.Tag}"/>
You can also negate the value of a binding using the ! operator:
<TextBox IsEnabled="{Binding !HasErrors}"/>
Here, the TextBox will only be enabled when the view model signals that it has no errors. Behind
the scenes, Avalonia tries to convert the incoming value to a boolean, and if it can be converted
it negates the value. If the incoming value cannot be converted to a boolean then no value will be
pushed to the binding target.
This syntax is specific to Avalonia.
You can subscribe to the result of a task or an observable by using the ^ stream binding operator.
<!-- If DataContext.Name is an IObservable<string> then this will bind to the length of each
string produced by the observable as each value is produced -->
<TextBlock Text="{Binding Name^.Length}"/>
This syntax is specific to Avalonia.
Note: the stream operator is actually extensible, see here for the interface to implement and here for the registration.