階層連結列

BreadcrumbBar 可提供頁面或資料夾的直接路徑至目前位置。 它通常用於使用者的導航軌跡 (在檔案系統或選單系統中) 需要持續可見並且使用者可能需要返回到先前位置的情況。

Breadcrumb bar with nodes: Home, Documents, Design, Northwind, Images, Folder1, Folder2, Folder3. The app is resized so that the Breadcrumb crumbles and an ellipsis replaces the leftmost nodes. Then, clicking the ellipsis opens a flyout with the crumbled nodes

這是正確的控制項嗎?

階層連結列可讓使用者在瀏覽應用程式或資料夾時追蹤自己的位置,並讓他們快速跳回路徑中的先前位置。

當到達目前位置的路徑相關時,請使用 BreadcrumbBar。 此 UI 通常用於資料夾管理器以及使用者可以深入瀏覽應用程式的多個層級時。

階層連結列以水平線顯示每個節點,並以 V 形分隔。

Breadcrumb bar with nodes: Home, Documents, Design, Northwind, Images, Folder1, Folder2, Folder3.

如果調整應用程式大小,導致沒有足夠的空間來顯示所有節點,則階層連結會折疊,省略號將替換最左邊的節點。 按兩下省略號會開啟飛出視窗以顯示折疊的節點。

Breadcrumb bar resized so that an ellipsis replaces the leftmost nodes. The ellipsis opens a flyout with that shows the collapsed nodes

結構

下圖顯示 BreadcrumbBar 控制項的各個部分。 您可以使用輕量型樣式來修改部分元件的外觀。

An image of a breadcrumb bar with the parts labeled: ellipsis, chevron, breadcrumb bar item, current item, ellipsis flyout, ellipsis drop down item

建議

  • 當您有多個導航等級並希望使用者能夠返回到任何先前等級時,請使用階層連結列。
  • 如果您只有 2 個可能的瀏覽層級,請勿使用階層連結列。 簡單的返回瀏覽就已足夠。
  • 將目前的位置顯示為階層連結列中的最後一個專案。 不過,如果使用者按兩下目前的專案,您通常不會想要執行任何瀏覽。 (如果您想要讓使用者重載目前的頁面或資料,請考慮提供專用的「重載」選項。)

UWP 和 WinUI 2

重要

本文中的資訊和範例針對使用 Windows App SDKWinUI 3 的應用程式進行了最佳化,但通常適用於使用 WinUI 2 的 UWP 應用程式。 如需平台特定資訊和範例,請參閱 UWP API 參考。

本節包含您在 UWP 或 WinUI 2 應用程式中使用控制項所需的資訊。

UWP app 的 BreadcrumbBar 需要 Windows UI 程式庫 2。 如需詳細資訊 (包括安裝指示),請參閱 Windows UI 程式庫。 此控制項的 API 位在 Microsoft.UI.Xaml.Controls 命名空間中。

若要在 WinUI 2 中使用本文中的程式碼,請在 XAML 中使用別名 (我們使用 muxc) 來表示專案中包含的 Windows UI 程式庫 API。 如需詳細資訊,請參閱開始使用 WinUI 2

xmlns:muxc="using:Microsoft.UI.Xaml.Controls"

<muxc:BreadcrumbBar />

建立階層連結列

WinUI 3 資源庫應用程式包含大多數 WinUI 3 控制項和功能的互動式範例。 從 Microsoft Store 取得應用程式,或在 GitHub 上取得原始程式碼

此範例示範如何使用預設樣式建立階層連結列。 您可以在應用程式 UI 中的任何位置放置階層連結列。 您可以藉由設定 ItemsSource 屬性來填入階層連結。 在這裡會設定為階層連結列中顯示的字串數位。

<BreadcrumbBar x:Name="BreadcrumbBar1"/>
BreadcrumbBar1.ItemsSource = 
   new string[] { "Home", "Documents", "Design", "Northwind", "Images", "Folder1", "Folder2", "Folder3" };

ItemsSource

階層連結列沒有 Items 屬性,就只有 ItemsSource 屬性。 這表示您無法在 XAML 中填入階層連結,或將階層連結直接新增至 Items 程式代碼中的集合。 相反地,您會建立集合,並在程式代碼中或使用資料系結將 ItemsSource 屬性連接到它。

您可以將 ItemsSource 設定為任何類型的資料集合,以符合應用程式的需求。 集合中的資料項目既用於在欄中顯示階層連結,也用於在點擊階層連結列中的項目時進行導覽。 在此頁面的範例中,我們建立一個簡單的 struct (名為 Crumb),其中包含要在階層連結列中顯示的標籤和保存用於導航的資訊的資料物件。

public readonly struct Crumb
{
    public Crumb(String label, object data)
    {
        Label = label;
        Data = data;
    }
    public string Label { get; }
    public object Data { get; }
    public override string ToString() => Label;
}

ItemTemplate

根據預設,階層連結列會顯示集合中每個專案的字串表示。 如果集合中的資料項沒有適當的 ToString 覆寫,您可以使用 ItemTemplate 屬性來指定資料範本,以定義專案在階層連結列中的顯示方式。

例如,如果您的階層連結集合是 StorageFolder 物件的列表,您可以提供資料模板並綁定到 DisplayName 屬性,如下所示。

ObservableCollection<StorageFolder> Breadcrumbs = 
    new ObservableCollection<StorageFolder>();
<BreadcrumbBar x:Name="FolderBreadcrumbBar"
            ItemsSource="{x:Bind Breadcrumbs}">
    <BreadcrumbBar.ItemTemplate>
        <DataTemplate x:DataType="StorageFolder">
            <TextBlock Text="{x:Bind DisplayName}"/>
        </DataTemplate>
    </BreadcrumbBar.ItemTemplate>
</BreadcrumbBar>

ItemClicked

處理 ItemClicked 事件,導覽至使用者在階層連結列中點擊的項目。 目前位置通常顯示為階層連結列中的最後一項,因此如果您不想重新載入目前位置,則應在事件處理程序中包含一個檢查

此範例檢查 Index 以查看按一下的 Item 是否是集合中的最後一項 (即目前位置)。 如果是,則不會發生瀏覽。

// Breadcrumbs is set as BreadcrumbBar1.ItemsSource.
List<Crumb> Breadcrumbs = new List<Crumb>();

...

private void BreadcrumbBar1_ItemClicked(muxc.BreadcrumbBar sender, muxc.BreadcrumbBarItemClickedEventArgs args)
{
    if (args.Index < Breadcrumbs.Count - 1)
    {
        var crumb = (Crumb)args.Item;
        Frame.Navigate((Type)crumb.Data);
    }
}

輕量化樣式

您可以修改預設樣式和 ControlTemplate,為控制項提供獨特的外觀。 如需可用主題資源的清單,請參閱 BreadcrumbBar API 文件的<控制項樣式和範本>一節。 如需詳細資訊,請參閱樣式控制項文章的輕量型樣式設定一節。

程式碼範例

此範例示範如何在簡單的檔案總管案例中使用階層連結列。 清單檢視顯示所選圖片或音樂庫的內容,並允許使用者深入查看子資料夾。 階層連結列列位於清單檢視的標題中,顯示目前資料夾的路徑。

An image of a file list with a breadcrumb bar showing the path to the current folder

<Grid>
   <ListView x:Name="FolderListView" Margin="24,0"
             IsItemClickEnabled="True" 
             ItemClick="FolderListView_ItemClick">
      <ListView.Header>
         <BreadcrumbBar x:Name="FolderBreadcrumbBar"
                             ItemsSource="{x:Bind Breadcrumbs}"
                             ItemClicked="FolderBreadcrumbBar_ItemClicked">
         </BreadcrumbBar>
      </ListView.Header>
      <ListView.ItemTemplate>
         <DataTemplate>
            <TextBlock Text="{Binding Name}"/>
            </DataTemplate>
      </ListView.ItemTemplate>
   </ListView>
</Grid>
public sealed partial class MainPage : Page
{
    List<IStorageItem> Items;
    ObservableCollection<object> Breadcrumbs = 
        new ObservableCollection<object>();

    public MainPage()
    {
        this.InitializeComponent();
        InitializeView();
    }

    private void InitializeView()
    {
        // Start with Pictures and Music libraries.
        Items = new List<IStorageItem>();
        Items.Add(KnownFolders.PicturesLibrary);
        Items.Add(KnownFolders.MusicLibrary);
        FolderListView.ItemsSource = Items;

        Breadcrumbs.Clear();
        Breadcrumbs.Add(new Crumb("Home", null));
    }

    private async void FolderBreadcrumbBar_ItemClicked(muxc.BreadcrumbBar sender, muxc.BreadcrumbBarItemClickedEventArgs args)
    {
        // Don't process last index (current location)
        if (args.Index < Breadcrumbs.Count - 1)
        {
            // Home is special case.
            if (args.Index == 0)
            {
                InitializeView();
            }
            // Go back to the clicked item.
            else
            {
                var crumb = (Crumb)args.Item;
                await GetFolderItems((StorageFolder)crumb.Data);

                // Remove breadcrumbs at the end until 
                // you get to the one that was clicked.
                while (Breadcrumbs.Count > args.Index + 1)
                {
                    Breadcrumbs.RemoveAt(Breadcrumbs.Count - 1);
                }
            }
        }
    }

    private async void FolderListView_ItemClick(object sender, ItemClickEventArgs e)
    {
        // Ignore if a file is clicked.
        // If a folder is clicked, drill down into it.
        if (e.ClickedItem is StorageFolder)
        {
            StorageFolder folder = e.ClickedItem as StorageFolder;
            await GetFolderItems(folder);
            Breadcrumbs.Add(new Crumb(folder.DisplayName, folder));
        }
    }

    private async Task GetFolderItems(StorageFolder folder)
    {
        IReadOnlyList<IStorageItem> itemsList = await folder.GetItemsAsync();
        FolderListView.ItemsSource = itemsList;
    }
}

public readonly struct Crumb
{
    public Crumb(String label, object data)
    {
        Label = label;
        Data = data;
    }
    public string Label { get; }
    public object Data { get; }
    public override string ToString() => Label;
}