分享方式:


BindableLayout

Browse sample. 流覽範例

.NET 多平臺應用程式 UI (.NET MAUI) 可系結版面配置可讓衍生自 Layout 類別的任何版面配置類別,藉由系結至專案集合來產生其內容,並可選擇使用 來設定每個項目 DataTemplate的外觀。

可系結的配置是由 BindableLayout 類別提供,其會公開下列附加屬性:

  • ItemsSource – 指定要由版面設定顯示的項目集合 IEnumerable
  • ItemTemplate – 指定要 DataTemplate 套用至版面設定所顯示項目集合中每個項目的 。
  • ItemTemplateSelector – 指定 DataTemplateSelector 在執行時間為項目選擇 DataTemplate 的 。

注意

設定 ItemTemplateItemTemplateSelector 屬性時ItemTemplate,屬性會優先使用。

此外,類別 BindableLayout 會公開下列可系結屬性:

  • EmptyView– 指定 string 當 屬性為 時,或 當 屬性nullItemsSource指定的集合為 null或空白時,將會顯示的 ItemsSource 或檢視。 預設值是 null
  • EmptyViewTemplate– 指定 DataTemplate 當 屬性為 時,ItemsSource或 當 屬性指定的集合為 nullnull 或空白時,將顯示的 ItemsSource 。 預設值是 null

注意

設定 EmptyViewTemplateEmptyViewTemplate 屬性時EmptyView,屬性會優先使用。

所有這些屬性都可以附加至 AbsoluteLayoutFlexLayout、、、GridHorizontalStackLayoutStackLayoutVerticalStackLayout 類別,這些屬性全都衍生自 Layout 類別。

BindableLayout.ItemsSource當屬性設定為專案集合並附加至Layout衍生類別時,集合中的每個項目都會新增至衍生類別以供Layout顯示。 Layout衍生類別會在基礎集合變更時更新其子檢視。

只有當要顯示的專案集合很小,而且不需要捲動和選取時,才應該使用可繫結的配置。 雖然捲動可以藉由在 中 ScrollView包裝可繫結的版面配置來提供,但不建議這麼做,因為可系結的配置缺少UI虛擬化。 需要捲動時,應該使用包含UI虛擬化的可捲動檢視,例如 ListViewCollectionView。 如果無法觀察這項建議,可能會導致效能問題。

重要

雖然從技術上講,可以將可系結的配置附加至衍生自 Layout 類別的任何版面配置類別,但對和 Grid 類別而言,AbsoluteLayout不一定可行。 例如,假設想要使用可系結配置在 中 Grid 顯示數據的集合,其中集合中的每個專案都是包含多個屬性的物件。 中的每個 Grid 數據列都應該顯示集合中的物件,其中每一個數據行都會 Grid 顯示其中一個對象的屬性。 DataTemplate因為可系結配置的 只能包含單一物件,所以該對象必須是包含多個檢視的版面配置類別,每個檢視都會在特定數據行中顯示其中一個Grid對象的屬性。 雖然此案例可以透過可系結的配置來實現,但會導致 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項目都會由 Label 類別所BindableLayout建立的 顯示。

定義項目外觀

您可以在可繫結設定中定義每個項目的外觀,方法是將 BindableLayout.ItemTemplate 附加屬性設定為 DataTemplate

<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 項目都會由 ImageDataTemplate定義的檢視顯示:

.NET MAUI bindable layout with a DataTemplate.

如需數據範本的詳細資訊,請參閱 數據範本

選擇運行時間的項目外觀

您可以藉由附加屬性設定 BindableLayout.ItemTemplateSelectorDataTemplateSelector,在執行時間根據專案值,選擇可繫結配置中每個項目的外觀:

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

類別 TechItemTemplateSelectorDefaultTemplate 定義 和 MAUITemplateDataTemplate 屬性,這些屬性會設定為不同的數據範本。 方法 OnSelectTemplateMAUITemplate傳回 ,當專案等於 “.NET MAUI” 時,會以深紅色顯示其旁邊的心形專案。 當專案不等於 「.NET MAUI」 時, OnSelectTemplate 方法會傳回 DefaultTemplate,它會使用的預設色彩 Label來顯示專案:

.NET MAUI bindable layout with a DataTemplateSelector.

如需數據範本選取器的詳細資訊,請參閱 建立 DataTemplateSelector

當數據無法使用時顯示字串

屬性EmptyView可以設定為字串,當 屬性為 nullItemsSource,或屬性所ItemsSource指定的集合為 null 或空白時,就會顯示Label該字串。 下列 XAML 顯示此案例的範例:

<StackLayout BindableLayout.ItemsSource="{Binding UserWithoutAchievements.Achievements}"
             BindableLayout.EmptyView="No achievements">
    ...
</StackLayout>

結果是,當數據系結集合為 null時,會顯示為 屬性值的 EmptyView 字串:

Screenshot of a bindable layout string empty view.

當數據無法使用時顯示檢視

屬性EmptyView可以設定為檢視,當 屬性為 nullItemsSource,或屬性指定的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 會顯示 及其子檢視。

Screenshot of a bindable layout empty view with multiple views.

同樣地,EmptyViewTemplate可以將 設定為 DataTemplate,當 屬性為 時ItemsSource,或 當 屬性指定的ItemsSource集合為 nullnull 或空白時,就會顯示該屬性。 DataTemplate可以包含單一檢視,或包含多個子檢視的檢視。 此外, BindingContextEmptyViewTemplate 會繼承自 BindingContextBindableLayout。 下列 XAML 範例顯示 EmptyViewTemplate 屬性設定為 DataTemplate 包含單一檢視的 :

<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時, Label 會顯示 中的 DataTemplate

Screenshot of a bindable layout empty view template.

注意

EmptyViewTemplate無法透過 DataTemplateSelector設定屬性。

在運行時間選擇 EmptyView

當數據無法使用時,會顯示為 EmptyView 的檢視,可以定義為 ContentView 中的 ResourceDictionary物件。 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中定義兩個 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,將 EmptyView 對象的 屬性StackLayout設定為儲存在 中ResourceDictionary之兩ContentView個 物件的其中一個。 然後,當數據系結集合為 null時, ContentView 就會顯示設定為 EmptyView 屬性的物件。