次の方法で共有


BindableLayout

サンプルを参照します。 サンプルを参照する

.NET Multi-Platform App UI (.NET MAUI) のバインド可能なレイアウトを使用すると、Layout クラスから派生したレイアウト クラスで、項目のコレクションにバインドすることによってコンテンツを生成できます。オプションで DataTemplate で各項目の外観を設定できます。

バインド可能なレイアウトは BindableLayout によって提供されます。このクラスは、次の添付プロパティを公開します。

  • ItemsSource: レイアウトによって表示される IEnumerable 項目のコレクションを指定します。
  • ItemTemplate: レイアウトで表示される項目のコレクション内の、各項目に適用する DataTemplate を指定します。
  • ItemTemplateSelector: 実行時に項目の DataTemplate を選択するために使用する DataTemplateSelector を指定します。

Note

たとえば、ItemTemplateItemTemplateSelector の両方のプロパティを設定した場合、ItemTemplate プロパティが優先されます。

さらに、BindableLayout クラスは次のバインド可能なプロパティを公開します。

  • EmptyView: ItemsSource プロパティが null の場合、または ItemsSource プロパティで指定されたコレクションが null または空の場合、表示される string またはビューを指定します。 既定値は null です。
  • EmptyViewTemplate: ItemsSource プロパティが null の場合、または ItemsSource プロパティで指定されたコレクションが null または空の場合、表示される DataTemplate を指定します。 既定値は null です。

Note

EmptyViewEmptyViewTemplate の両方のプロパティを設定した場合、EmptyViewTemplate プロパティが優先されます。

これらのプロパティはすべて、AbsoluteLayoutFlexLayoutGridHorizontalStackLayoutStackLayoutVerticalStackLayout クラスにアタッチできます。これらはすべて 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 によって表示されます。

項目の外観を定義

バインド可能なレイアウト内の各項目の外観は、添付プロパティ DataTemplateBindableLayout.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 ビューによって表示されます。

.NET MAUI のバインド可能なレイアウトと DataTemplate。

データ テンプレートの詳細については、「データ テンプレート」をご覧ください。

実行時にアイテムの外観を選択

バインド可能なレイアウト内の各項目の外観は、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 色を使用して項目を表示します。

.NET MAUI のバインド可能なレイアウトと DataTemplateSelector。

データ テンプレート セレクターの詳細については、「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 とその子ビューが表示されます。

複数のビューを含むバインド可能なレイアウトの空のビューのスクリーンショット。

同様に、EmptyViewTemplateDataTemplate に設定できます。これは、ItemsSource プロパティが null の場合、または ItemsSource プロパティで指定されたコレクションが null または空の場合に表示されます。 DataTemplate には、単一のビュー、または複数の子ビューを含むビューを含めることができます。 さらに、EmptyViewTemplateBindingContext は、BindableLayoutBindingContext から継承されます。 次の 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 オブジェクトが表示されます。