Xamarin.Forms Binding Fallbacks
Sometimes data bindings fail, because the binding source can't be resolved, or because the binding succeeds but returns a null
value. While these scenarios can be handled with value converters, or other additional code, data bindings can be made more robust by defining fallback values to use if the binding process fails. This can be accomplished by defining the FallbackValue
and TargetNullValue
properties in a binding expression. Because these properties reside in the BindingBase
class, they can be used with bindings, multi-bindings, compiled bindings, and with the Binding
markup extension.
Note
Use of the FallbackValue
and TargetNullValue
properties in a binding expression is optional.
Defining a fallback value
The FallbackValue
property allows a fallback value to be defined that will be used when the binding source can't be resolved. A common scenario for setting this property is when binding to source properties that might not exist on all objects in a bound collection of heterogeneous types.
The MonkeyDetail page illustrates setting the FallbackValue
property:
<Label Text="{Binding Population, FallbackValue='Population size unknown'}"
... />
The binding on the Label
defines a FallbackValue
value that will be set on the target if the binding source can't be resolved. Therefore, the value defined by the FallbackValue
property will be displayed if the Population
property doesn't exist on the bound object. Notice that here the FallbackValue
property value is delimited by single-quote (apostrophe) characters.
Rather than defining FallbackValue
property values inline, it's recommended to define them as resources in a ResourceDictionary
. The advantage of this approach is that such values are defined once in a single location, and are more easily localizable. The resources can then be retrieved using the StaticResource
markup extension:
<Label Text="{Binding Population, FallbackValue={StaticResource populationUnknown}}"
... />
Note
It's not possible to set the FallbackValue
property with a binding expression.
Here's the program running:
When the FallbackValue
property isn't set in a binding expression and the binding path or part of the path isn't resolved, BindableProperty.DefaultValue
is set on the target. However, when the FallbackValue
property is set and the binding path or part of the path isn't resolved, the value of the FallbackValue
value property is set on the target. Therefore, on the MonkeyDetail page the Label
displays "Population size unknown" because the bound object lacks a Population
property.
Important
A defined value converter is not executed in a binding expression when the FallbackValue
property is set.
Defining a null replacement value
The TargetNullValue
property allows a replacement value to be defined that will be used when the binding source is resolved, but the value is null
. A common scenario for setting this property is when binding to source properties that might be null
in a bound collection.
The Monkeys page illustrates setting the TargetNullValue
property:
<ListView ItemsSource="{Binding Monkeys}"
...>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
...
<Image Source="{Binding ImageUrl, TargetNullValue='https://upload.wikimedia.org/wikipedia/commons/2/20/Point_d_interrogation.jpg'}"
... />
...
<Label Text="{Binding Location, TargetNullValue='Location unknown'}"
... />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The bindings on the Image
and Label
both define TargetNullValue
values that will be applied if the binding path returns null
. Therefore, the values defined by the TargetNullValue
properties will be displayed for any objects in the collection where the ImageUrl
and Location
properties are not defined. Notice that here the TargetNullValue
property values are delimited by single-quote (apostrophe) characters.
Rather than defining TargetNullValue
property values inline, it's recommended to define them as resources in a ResourceDictionary
. The advantage of this approach is that such values are defined once in a single location, and are more easily localizable. The resources can then be retrieved using the StaticResource
markup extension:
<Image Source="{Binding ImageUrl, TargetNullValue={StaticResource fallbackImageUrl}}"
... />
<Label Text="{Binding Location, TargetNullValue={StaticResource locationUnknown}}"
... />
Note
It's not possible to set the TargetNullValue
property with a binding expression.
Here's the program running:
When the TargetNullValue
property isn't set in a binding expression, a source value of null
will be converted if a value converter is defined, formatted if a StringFormat
is defined, and the result is then set on the target. However, when the TargetNullValue
property is set, a source value of null
will be converted if a value converter is defined, and if it's still null
after the conversion, the value of the TargetNullValue
property is set on the target.
Important
String formatting is not applied in a binding expression when the TargetNullValue
property is set.