XAML でデータ バインディングを使用する
- 6 分
マークアップ拡張を使用して、コードまたは XAML でデータ バインディングを宣言できます。 このユニットでは、バインディングを作成する最も一般的な方法であるため、後者について説明します。 XAML を選ぶ理由はいくつかあります。 第一に、バインドによって UI で表示するためのデータを取得するため、ほとんどの人がバインドは UI コードの一部だと考えています。 第二に、作業を簡単にする Binding という名前のマークアップ拡張があります。
データ バインディングとは
"バインド" によって 2 つのプロパティを連結します。 1 つのプロパティは UI に、もう 1 つはデータモデル オブジェクトに含まれます。 いずれかのプロパティの値が変更されると、バインド オブジェクトによりもう 1 つが更新されます。 つまり、バインドは UI とデータを同期する中間オブジェクトです。 ここでは "ソース" と "ターゲット" という用語を使って、関連する 2 つのオブジェクトを識別します。
ソース:ソースは任意の種類のオブジェクトにできます。 実際には、通常、ソースとしてデータ オブジェクトを使用します。 バインドに加えるには、そのソース オブジェクト上のプロパティを識別する必要があります。 バインディングで
Pathプロパティを設定することで、プロパティを識別します。ターゲット: ターゲットは、
BindablePropertyという特殊なプロパティを使って実装するプロパティです。BindablePropertyを持つオブジェクトは、BindableObjectから派生する必要があります。 .NET MAUI で提供されるすべてのコントロールはBindableObjectから派生し、そのプロパティのほとんどはBindableProperties。
次の図は、バインディングが 2 つのプロパティ間の中間オブジェクトとなる様子を示しています。
XAML でデータ バインディングを作成する方法
XAML で {Binding} マークアップ拡張を使って作成したシンプルなバインディングを見てみましょう。 ソースの WeatherService.Humidity プロパティが、UI コントロールの Text プロパティにバインドされています。
<VerticalStackLayout Margin="10">
<VerticalStackLayout.Resources>
<ResourceDictionary>
<services:WeatherService x:Key="myWeatherService" />
</ResourceDictionary>
</VerticalStackLayout.Resources>
<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" />
</VerticalStackLayout>
このバインディング ソースは:
WeatherService型のオブジェクト インスタンスです。 このインスタンスは、{StaticResource ...}XAML 拡張機能を通じて参照され、スタック レイアウトのリソース ディクショナリ内のオブジェクトを指します。Pathは、Humidity型のWeatherServiceという名前のプロパティを指します。Pathは、{Binding}構文の最初の無名パラメーターであり、Path=構文は省略できます。 次の 2 つのバインディングは等価です。<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" /> <Label Text="{Binding Humidity, Source={StaticResource myWeatherService}}" />
バインディング ターゲットは次のとおりです。
-
Labelコントロール。 - コントロールの
Textプロパティ。
UI が表示されるときに、{Binding} XAML 拡張によって、WeatherService と Label のバインディングが作成されます。 このバインディングにより、WeatherService.Humidity プロパティの値が Label.Text プロパティに読み取られます。
バインディング ソースとして別のコントロールを使う
バインディングの便利な機能の 1 つは、別のコントロールにバインドできることです。 次の XAML は、シンプルなデモです。
<VerticalStackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Label x:Name="TargetLabel" Text="TEXT TO ROTATE" BackgroundColor="Yellow" />
<Slider WidthRequest="100" Maximum="360"
Value="{Binding Rotation, Mode=OneWayToSource, Source={x:Reference TargetLabel}}" />
</VerticalStackLayout>
Slider.Value プロパティを、前の説明とは違う方法で Label.Rotation プロパティにバインドしています。 このプロパティは、通常のバインド メカニズムを反転させるバインド モード OneWayToSource を使用しています。
では、ソースでOneWayToSourceを更新する代わりに、ターゲットが変更されたときにソースを更新します。 この例では、次のアニメーションに示すように、スライダーを移動すると、そのスライダーの値に基づいてラベルの回転が更新されます。
コントロールを相互にバインドする一般的なシナリオは、コントロール (通常は CollectionView や CarouselViewなどのコレクション コントロール) に、データ ソースとして使用する選択された項目がある場合です。 天気予報を表示するページの例では、5 日間の予報を示す CollectionView を使用できます。 ユーザーがリストの曜日を選択すると、その天気予報の詳細が他のコントロールに表示されます。 ユーザーが別の曜日を選択すると、その選択した曜日の詳細によって再び他のコントロールが更新されます。
注
.NET MAUI 10 では、 ListView は非推奨となり、 CollectionViewが優先されます。
CollectionViewを使用して、新しいアプリケーションのデータの一覧を表示します。
複数のバインディングで同じソースを使う
前の例では、静的リソースを 1 つのバインディングのソースとして使う方法を示しました。 そのソースは、複数のバインディングで使用できます。 ここでは、3 つの異なるコントロールにわたるバインディングを宣言する例を示します。すべて同じオブジェクトとプロパティ Path に対してバインディングしていますが、一部では Path プロパティを省略しています。
<VerticalStackLayout Margin="10">
<VerticalStackLayout.Resources>
<vm:SimpleWeatherServiceObject x:Key="myWeatherService" />
</VerticalStackLayout.Resources>
<Entry Text="{Binding Humidity, Source={StaticResource myWeatherService}}" />
<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" />
</VerticalStackLayout>
同じ Path を使用するときに同じ Source を使用する必要はありません。
<VerticalStackLayout Margin="10">
<VerticalStackLayout.Resources>
<vm:SimpleWeatherServiceObject x:Key="myWeatherService" />
</VerticalStackLayout.Resources>
<Entry Text="{Binding Temperature, Source={StaticResource myWeatherService}}" />
<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" />
</VerticalStackLayout>
ソースから 1 つのデータを示すことはまれですが、まったくないわけではありません。 通常、同じソースの異なるデータを使用するコントロールがいくつかあります。 このような状況は非常に一般的なので、BindableObject クラスには、データ バインディングのソースとして機能する BindingContext という名前のプロパティがあります。 .NET MAUI コントロールは BindableObject クラスを継承することを思い出してください。そのため、.NET MAUI コントロールには BindingContext プロパティがあります。
バインド Source の設定は省略可能です。
Source が設定されていないバインディングでは、BindingContext の XAML ビジュアル ツリーが自動的に検索されます。これは XAML で設定するか、コードによって親要素に割り当てます。 バインディングは、次のパターンに従って評価されます。
バインディングで
Sourceが定義されている場合、そのソースが使用され、検索は停止します。 バインディングのPathをSourceに適用して、値を取得します。Sourceが設定されていない場合は、バインディング ソースの検索が始まります。検索はターゲット オブジェクト自体から始まります。 ターゲット オブジェクトの
BindingContextが null でない場合は、検索を停止し、バインディングのPathをBindingContextに適用して値を取得します。BindingContextが null だった場合は、検索を続行します。このプロセスは、XAML ルートに到達するまで続きます。 ルートの
BindingContextが null 以外の値であるかどうかをチェックして、検索は終了します。 有効なBindingContextが見つからなかった場合、そのバインディングはバインド対象が存在せず、何も行いません。
ルート オブジェクトのレベルで BindingContext を設定し、XAML 全体に適用するのが一般的です。
最後に、もう 1 つの便利な機能について説明します。 バインドでは、各ソースの "オブジェクト参照" に対する変更が監視されます。 これは、ソースとして BindingContext を使っているバインディングに対しても機能します。
Source または BindingContext が別のオブジェクトに再割り当てされると、バインドによって新しいソースからデータが取得され、そのターゲットが更新されます。