Поділитися через


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:

FallbackValue Binding

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:

TargetNullValue Binding

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.