Xamarin.Forms でのバインドのフォールバック

バインディング ソースを解決できないため、またはバインドは成功しても null 値が返されるために、データ バインディングが失敗する場合があります。 これらのシナリオについては、値コンバーターまたは他の追加コードで対処できますが、バインド プロセスが失敗した場合に使用されるフォールバック値を定義することでデータ バインディングをより堅牢にすることができます。 このためには、バインド式で FallbackValue プロパティと TargetNullValue プロパティを定義します。 これらのプロパティは、BindingBase クラス内にあるため、バインド、複数バインド、コンパイル済みのバインド、Binding マークアップ拡張で使用することができます。

Note

バインド式での FallbackValue プロパティと TargetNullValue プロパティの使用は任意です。

フォールバック値の定義

FallbackValue プロパティを使用すると、バインディング ソースを解決できない場合に使用されるフォールバック値を定義できます。 このプロパティを設定する一般的なシナリオは、バインドされた異種型コレクション内のすべてのオブジェクトに存在しない可能性のあるソース プロパティにバインドする場合です。

次の MonkeyDetail ページは、FallbackValue プロパティの設定例を示します。

<Label Text="{Binding Population, FallbackValue='Population size unknown'}"
       ... />   

Label でのバインドは、バインディング ソースを解決できない場合にターゲットで設定される FallbackValue 値を定義します。 このため、FallbackValue プロパティで定義される値は、バインドされたオブジェクトに Population プロパティが存在しない場合に表示されます。 ここでは、FallbackValue プロパティ値が一重引用符 (アポストロフィ) 文字で区切られていることに注意してください。

FallbackValue プロパティ値をインラインで定義しないで、ResourceDictionary でリソースとして定義することをお勧めします。 この方法を使用すると、このような値を 1 か所で 1 回定義するだけで済み、ローカライズがより簡単になるという利点があります。 リソースは、StaticResource マークアップ拡張を使用して取得することができます。

<Label Text="{Binding Population, FallbackValue={StaticResource populationUnknown}}"
       ... />  

Note

バインド式を使用して FallbackValue を設定することはできません。

実行中のプログラムを次に示します。

FallbackValue のバインド

バインド式に FallbackValue プロパティが設定されておらず、バインド パスまたはその一部が解決されない場合、ターゲットでは、BindableProperty.DefaultValue が設定されます。 一方、バインド式に FallbackValue プロパティが設定されており、バインド パスまたはその一部が解決されない場合、ターゲットでは、FallbackValue 値プロパティの値が設定されます。 したがって、MonkeyDetail ページでは、バインドされたオブジェクトに Population プロパティがないため、Label により、"Population size unknown" (作成サイズが不明) が表示されます。

重要

FallbackValue プロパティが設定されている場合、バインド式で、定義済みの値コンバーターは実行されません。

null の置換値の定義

TargetNullValue プロパティを使用すると、バインド ソースは解決できても値が null である場合に使用される置換値を定義できます。 このプロパティを設定する一般的なシナリオは、値が null である可能性のある、バインド コレクション内のソース プロパティにバインドする場合です。

次の Monkeys ページは、TargetNullValue プロパティの設定例を示します。

<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>

Image および Label でのバインドは両方とも、バインド パスが null を返す場合に適用される TargetNullValue 値を定義します。 このため、ImageUrl および Location が定義されていない場合、コレクション内のオブジェクトに対して TargetNullValue で定義された値が表示されます。 ここでは、TargetNullValue プロパティ値が一重引用符 (アポストロフィ) 文字で区切られていることに注意してください。

TargetNullValue プロパティ値をインラインで定義しないで、ResourceDictionary でリソースとして定義することをお勧めします。 この方法を使用すると、このような値を 1 か所で 1 回定義するだけで済み、ローカライズがより簡単になるという利点があります。 リソースは、StaticResource マークアップ拡張を使用して取得することができます。

<Image Source="{Binding ImageUrl, TargetNullValue={StaticResource fallbackImageUrl}}"
       ... />
<Label Text="{Binding Location, TargetNullValue={StaticResource locationUnknown}}"
       ... />

Note

バインド式を使用して TargetNullValue を設定することはできません。

実行中のプログラムを次に示します。

TargetNullValue のバインド

バインド式に TargetNullValue プロパティが設定されていない場合、ソース値の null は、変換され (値コンバーターが定義されている場合)、書式設定された (StringFormat が定義されている場合) 後、その結果がターゲットで設定されます。 一方、TargetNullValue プロパティが設定されている場合、ソース値 null は、値コンバーターが定義されていれば変換されます。変換後も null のままであれば、ターゲットでは TargetNullValue プロパティの値が設定されます。

重要

TargetNullValue プロパティが設定されている場合、バインド式で文字列の書式設定は適用されません。