BindableLayout
.NET Multi-Platform App UI (.NET MAUI) のバインド可能なレイアウトを使用すると、Layout クラスから派生したレイアウト クラスで、項目のコレクションにバインドすることによってコンテンツを生成できます。オプションで DataTemplate で各項目の外観を設定できます。
バインド可能なレイアウトは BindableLayout によって提供されます。このクラスは、次の添付プロパティを公開します。
ItemsSource
: レイアウトによって表示されるIEnumerable
項目のコレクションを指定します。ItemTemplate
: レイアウトで表示される項目のコレクション内の、各項目に適用する DataTemplate を指定します。ItemTemplateSelector
: 実行時に項目の DataTemplate を選択するために使用する DataTemplateSelector を指定します。
Note
たとえば、ItemTemplate
と ItemTemplateSelector
の両方のプロパティを設定した場合、ItemTemplate
プロパティが優先されます。
さらに、BindableLayout クラスは次のバインド可能なプロパティを公開します。
EmptyView
:ItemsSource
プロパティがnull
の場合、またはItemsSource
プロパティで指定されたコレクションがnull
または空の場合、表示されるstring
またはビューを指定します。 既定値はnull
です。EmptyViewTemplate
:ItemsSource
プロパティがnull
の場合、またはItemsSource
プロパティで指定されたコレクションがnull
または空の場合、表示される DataTemplate を指定します。 既定値はnull
です。
Note
EmptyView
と EmptyViewTemplate
の両方のプロパティを設定した場合、EmptyViewTemplate
プロパティが優先されます。
これらのプロパティはすべて、AbsoluteLayout、FlexLayout、Grid、HorizontalStackLayout、StackLayout、VerticalStackLayout クラスにアタッチできます。これらはすべて Layout クラスから派生します。
BindableLayout.ItemsSource
プロパティが項目のコレクションに設定され、Layout から派生したクラスにアタッチされると、コレクション内の各項目が Layout から派生したクラスに追加されて表示されます。 その後、基になるコレクションが変更されると、Layout から派生したクラスによって子のビューが更新されます。
バインド可能なレイアウトは、表示する項目のコレクションが小さく、スクロールと選択が必要ない場合にのみ使用してください。 ScrollView ではスクロールはバインド可能なレイアウトをラップすることによって提供できますが、バインド可能なレイアウトには UI 仮想化がないため、これはお勧めしません。 スクロールが必要な場合は、UI 仮想化を含むスクロール可能なビュー (CollectionView または ListView など) を使用する必要があります。 この推奨事項を守らないと、パフォーマンスの問題が発生する可能性があります。
重要
Layout クラスから派生したレイアウト クラスにバインド可能なレイアウトをアタッチすることは技術的には可能ですが、特に AbsoluteLayout クラスと Grid クラスの場合、そうすることは必ずしも現実的ではありません。 たとえば、バインド可能なレイアウトを使用して Grid のデータのコレクションを表示するシナリオを考えてみましょう。この場合、コレクション内の各項目は複数のプロパティを含むオブジェクトです。 Grid の各行にはコレクションのオブジェクトが表示され、Grid の各列にはオブジェクトのプロパティの 1 つが表示されます。 バインド可能なレイアウトの DataTemplate には 1 つのオブジェクトしか含めることができないため、そのオブジェクトは、特定の Grid 列にオブジェクトのプロパティの 1 つをそれぞれ表示する複数のビューを含むレイアウト クラスである必要があります。 このシナリオはバインド可能なレイアウトで実現できますが、バインドされたコレクション内の各アイテムの子 Grid を含む親 Grid が作成されることになります。これは、Grid レイアウトの非常に非効率的で問題のある使用方法です。
バインド可能なレイアウトへのデータの設定
バインド可能なレイアウトには、ItemsSource
プロパティを IEnumerable
を実装するコレクションに設定し、Layout 派生クラスにアタッチすることでデータが設定されます。
<Grid BindableLayout.ItemsSource="{Binding Items}" />
同等の C# コードを次に示します。
IEnumerable<string> items = ...;
Grid grid = new Grid();
BindableLayout.SetItemsSource(grid, items);
BindableLayout.ItemsSource
添付プロパティがレイアウトに設定されているが、BindableLayout.ItemTemplate
添付プロパティが設定されていない場合、IEnumerable
コレクション内のすべての項目は、BindableLayout クラスによって作成された Label によって表示されます。
項目の外観を定義
バインド可能なレイアウト内の各項目の外観は、添付プロパティ DataTemplate を BindableLayout.ItemTemplate
に設定することで定義できます。
<StackLayout BindableLayout.ItemsSource="{Binding User.TopFollowers}"
Orientation="Horizontal"
...>
<BindableLayout.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}"
Aspect="AspectFill"
WidthRequest="44"
HeightRequest="44"
... />
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
同等の C# コードを次に示します。
DataTemplate imageTemplate = ...;
StackLayout stackLayout = new StackLayout();
BindableLayout.SetItemsSource(stackLayout, viewModel.User.TopFollowers);
BindableLayout.SetItemTemplate(stackLayout, imageTemplate);
この例では、TopFollowers
コレクション内のすべての項目は、DataTemplate で定義されている Image ビューによって表示されます。
データ テンプレートの詳細については、「データ テンプレート」をご覧ください。
実行時にアイテムの外観を選択
バインド可能なレイアウト内の各項目の外観は、BindableLayout.ItemTemplateSelector
添付プロパティを DataTemplateSelector に設定することで、項目の値に基づいて実行時に選択できます。
<FlexLayout BindableLayout.ItemsSource="{Binding User.FavoriteTech}"
BindableLayout.ItemTemplateSelector="{StaticResource TechItemTemplateSelector}"
... />
同等の C# コードを次に示します。
DataTemplateSelector dataTemplateSelector = new TechItemTemplateSelector { ... };
FlexLayout flexLayout = new FlexLayout();
BindableLayout.SetItemsSource(flexLayout, viewModel.User.FavoriteTech);
BindableLayout.SetItemTemplateSelector(flexLayout, dataTemplateSelector);
次の例は、TechItemTemplateSelector
クラスを示しています。
public class TechItemTemplateSelector : DataTemplateSelector
{
public DataTemplate DefaultTemplate { get; set; }
public DataTemplate MAUITemplate { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
return (string)item == ".NET MAUI" ? MAUITemplate : DefaultTemplate;
}
}
TechItemTemplateSelector
クラスは、異なるデータ テンプレートに設定される DefaultTemplate
および MAUITemplate
DataTemplate プロパティを定義します。 OnSelectTemplate
メソッドは MAUITemplate
を返します。これは、項目が ".NET MAUI" と等しい場合、項目を濃い赤色で表示し、横にハートを表示します。 項目が ".NET MAUI" と等しくない場合、OnSelectTemplate
メソッドは DefaultTemplate
を返します。これは、既定の Label 色を使用して項目を表示します。
データ テンプレート セレクターの詳細については、「DataTemplateSelector の作成」をご覧ください。
データが使用できないときに文字列を表示
EmptyView
プロパティは文字列に設定できます。これは、ItemsSource
プロパティが null
の場合、または ItemsSource
プロパティで指定されたコレクションが null
または空の場合、Label によって表示されます。 次の XAML は、このシナリオの例を示しています。
<StackLayout BindableLayout.ItemsSource="{Binding UserWithoutAchievements.Achievements}"
BindableLayout.EmptyView="No achievements">
...
</StackLayout>
その結果、データ バインドされたコレクションが null
の場合、EmptyView
プロパティ値として設定された文字列が表示されます。
データが使用できない場合にビューを表示する
EmptyView
プロパティはビューに設定できます。このビューは、ItemsSource
プロパティが null
の場合、または ItemsSource
プロパティで指定されたコレクションが null
または空の場合に表示されます。 単一のビューでも、複数の子ビューを含むビューでも表示できます。 次の XAML の例は、複数の子ビューを含むビューに設定された EmptyView
プロパティを示しています。
<StackLayout BindableLayout.ItemsSource="{Binding UserWithoutAchievements.Achievements}">
<BindableLayout.EmptyView>
<StackLayout>
<Label Text="None."
FontAttributes="Italic"
FontSize="{StaticResource smallTextSize}" />
<Label Text="Try harder and return later?"
FontAttributes="Italic"
FontSize="{StaticResource smallTextSize}" />
</StackLayout>
</BindableLayout.EmptyView>
...
</StackLayout>
その結果、データ バインドされたコレクションが null
の場合、StackLayout とその子ビューが表示されます。
同様に、EmptyViewTemplate
を DataTemplate に設定できます。これは、ItemsSource
プロパティが null
の場合、または ItemsSource
プロパティで指定されたコレクションが null
または空の場合に表示されます。 DataTemplate には、単一のビュー、または複数の子ビューを含むビューを含めることができます。 さらに、EmptyViewTemplate
の BindingContext
は、BindableLayout の BindingContext
から継承されます。 次の XAML の例は、単一のビューを含む DataTemplate に設定された EmptyViewTemplate
プロパティを示しています。
<StackLayout BindableLayout.ItemsSource="{Binding UserWithoutAchievements.Achievements}">
<BindableLayout.EmptyViewTemplate>
<DataTemplate>
<Label Text="{Binding Source={x:Reference usernameLabel}, Path=Text, StringFormat='{0} has no achievements.'}" />
</DataTemplate>
</BindableLayout.EmptyViewTemplate>
...
</StackLayout>
その結果、データ バインドされたコレクションが null
の場合、DataTemplate 内の Label が表示されます。
Note
EmptyViewTemplate
プロパティは DataTemplateSelector を介して設定できません。
実行時に EmptyView を選択する
データを使用できない場合に EmptyView
として表示されるビューは、ResourceDictionary 内の ContentView オブジェクトとして定義できます。 EmptyView
プロパティは、実行時にビジネス ロジックに基づいて特定の ContentView に設定できます。 次の XAML は、このシナリオの例を示しています。
<ContentPage ...>
<ContentPage.Resources>
...
<ContentView x:Key="BasicEmptyView">
<StackLayout>
<Label Text="No achievements."
FontSize="14" />
</StackLayout>
</ContentView>
<ContentView x:Key="AdvancedEmptyView">
<StackLayout>
<Label Text="None."
FontAttributes="Italic"
FontSize="14" />
<Label Text="Try harder and return later?"
FontAttributes="Italic"
FontSize="14" />
</StackLayout>
</ContentView>
</ContentPage.Resources>
<StackLayout>
...
<Switch Toggled="OnEmptyViewSwitchToggled" />
<StackLayout x:Name="stackLayout"
BindableLayout.ItemsSource="{Binding UserWithoutAchievements.Achievements}">
...
</StackLayout>
</StackLayout>
</ContentPage>
XAML では、ページレベル ResourceDictionary に 2 つの ContentView オブジェクトが定義されており、Switch オブジェクトは、どの ContentView オブジェクトを EmptyView
プロパティ値として設定するかを制御します。 Switch が切り替わると、OnEmptyViewSwitchToggled
イベント ハンドラーは ToggleEmptyView
メソッドを実行します。
void ToggleEmptyView(bool isToggled)
{
object view = isToggled ? Resources["BasicEmptyView"] : Resources["AdvancedEmptyView"];
BindableLayout.SetEmptyView(stackLayout, view);
}
ToggleEmptyView
メソッドは、Switch.IsToggled
プロパティの値に基づいて、StackLayout オブジェクトの EmptyView
プロパティを、ResourceDictionary に保存されている 2 つの ContentView オブジェクトのいずれかに設定します。 次に、データ バインドされたコレクションが null
の場合、EmptyView
プロパティとして設定された ContentView オブジェクトが表示されます。
.NET MAUI