Pemandangan pohon

Kontrol tampilan pohon memungkinkan daftar hierarkis dengan memperluas dan menciutkan simpul yang berisi item berlapis. Ini dapat digunakan untuk mengilustrasikan struktur folder atau hubungan berlapis di UI Anda.

Tampilan pohon menggunakan kombinasi indentasi dan ikon untuk mewakili hubungan berlapis antara simpul induk dan simpul anak. Simpul yang diciutkan menggunakan chevron yang menunjuk ke kanan, dan node yang diperluas menggunakan chevron yang menunjuk ke bawah.

The chevron icon in TreeView

Anda dapat menyertakan ikon dalam templat data item tampilan pohon untuk mewakili simpul. Misalnya, jika Anda menampilkan hierarki sistem file, Anda dapat menggunakan ikon folder untuk catatan induk dan ikon file untuk simpul daun.

The chevron and folder icons together in a TreeView

TREEView API mendukung fitur-fitur berikut:

  • Bersarang tingkat N
  • Pilihan simpul tunggal atau beberapa
  • Pengikatan data ke properti ItemsSource di TreeView dan TreeViewItem
  • TreeViewItem sebagai akar templat item TreeView
  • Jenis konten arbitrer dalam TreeViewItem
  • Seret dan letakkan di antara tampilan pohon

Apakah ini kontrol yang tepat?

  • Gunakan TreeView saat item memiliki item daftar berlapis, dan jika penting untuk mengilustrasikan hubungan hierarkis item dengan rekan dan simpul mereka.

  • Hindari menggunakan TreeView jika menyoroti hubungan berlapis item bukanlah prioritas. Untuk sebagian besar skenario penelusuran, tampilan daftar reguler sesuai.

UWP dan WinUI 2

Penting

Informasi dan contoh dalam artikel ini dioptimalkan untuk aplikasi yang menggunakan SDK Aplikasi Windows dan WinUI 3, tetapi umumnya berlaku untuk aplikasi UWP yang menggunakan WinUI 2. Lihat referensi API UWP untuk informasi dan contoh spesifik platform.

Bagian ini berisi informasi yang Anda butuhkan untuk menggunakan kontrol di aplikasi UWP atau WinUI 2.

TreeView untuk aplikasi UWP disertakan sebagai bagian dari Windows UI Library 2. Untuk informasi selengkapnya, termasuk instruksi penginstalan, lihat Pustaka UI Windows. API untuk kontrol ini ada di namespace Windows.UI.Xaml.Controls (UWP) dan Microsoft.UI.Xaml.Controls (WinUI).

Sebaiknya gunakan WinUI 2 terbaru untuk mendapatkan gaya, templat, dan fitur terbaru untuk semua kontrol.

Untuk menggunakan kode dalam artikel ini dengan WinUI 2, gunakan alias di XAML (kami menggunakan muxc) untuk mewakili API Pustaka Windows UI yang disertakan dalam proyek Anda. Lihat Mulai menggunakan WinUI 2 untuk informasi selengkapnya.

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

<muxc:TreeView>
    <muxc:TreeView.RootNodes>
        <muxc:TreeViewNode Content="Flavors">
            <muxc:TreeViewNode.Children>
                <muxc:TreeViewNode Content="Vanilla"/>
            </muxc:TreeViewNode.Children>
        </muxc:TreeViewNode>
    </muxc:TreeView.RootNodes>
</muxc:TreeView>

Membuat tampilan pohon

Anda dapat membuat tampilan pohon dengan mengikat ItemsSource ke sumber data hierarkis, atau Anda dapat membuat dan mengelola objek TreeViewNode sendiri.

Untuk membuat tampilan pohon, Anda menggunakan kontrol TreeView dan hierarki objek TreeViewNode . Anda membuat hierarki simpul dengan menambahkan satu atau beberapa simpul akar ke koleksi RootNodes kontrol TreeView. Setiap TreeViewNode kemudian dapat memiliki lebih banyak simpul yang ditambahkan ke koleksi Anak-anaknya. Anda dapat menumpuk simpul tampilan pohon ke kedalaman apa pun yang Anda butuhkan.

Anda dapat mengikat sumber data hierarkis ke properti ItemsSource untuk menyediakan konten tampilan pohon, seperti yang Anda lakukan dengan ItemsSource ListView. Demikian pula, gunakan ItemTemplate (dan ItemTemplateSelector opsional) untuk menyediakan DataTemplate yang merender item.

Penting

ItemsSource dan API terkait memerlukan Windows 10, versi 1809 (SDK 17763) atau yang lebih baru, atau Pustaka UI Windows.

ItemsSource adalah mekanisme alternatif untuk TreeView.RootNodes untuk memasukkan konten ke dalam kontrol TreeView . Anda tidak dapat mengatur ItemSource dan RootNodes secara bersamaan. Saat Anda menggunakan ItemsSource, simpul dibuat untuk Anda, dan Anda dapat mengaksesnya dari properti TreeView.RootNodes .

Berikut adalah contoh tampilan pohon sederhana yang dideklarasikan dalam XAML. Anda biasanya menambahkan simpul dalam kode, tetapi kami menunjukkan hierarki XAML di sini karena dapat membantu untuk memvisualisasikan bagaimana hierarki simpul dibuat.

<muxc:TreeView>
    <muxc:TreeView.RootNodes>
        <muxc:TreeViewNode Content="Flavors"
                           IsExpanded="True">
            <muxc:TreeViewNode.Children>
                <muxc:TreeViewNode Content="Vanilla"/>
                <muxc:TreeViewNode Content="Strawberry"/>
                <muxc:TreeViewNode Content="Chocolate"/>
            </muxc:TreeViewNode.Children>
        </muxc:TreeViewNode>
    </muxc:TreeView.RootNodes>
</muxc:TreeView>

Dalam kebanyakan kasus, tampilan pohon Anda menampilkan data dari sumber data, jadi Anda biasanya mendeklarasikan kontrol TreeView akar di XAML, tetapi menambahkan objek TreeViewNode dalam kode atau menggunakan pengikatan data.

Ikat ke sumber data hierarkis

Untuk membuat tampilan pohon menggunakan pengikatan data, atur kumpulan hierarkis ke properti TreeView.ItemsSource . Kemudian di ItemTemplate, atur kumpulan item anak ke properti TreeViewItem.ItemsSource .

<muxc:TreeView ItemsSource="{x:Bind DataSource}">
    <muxc:TreeView.ItemTemplate>
        <DataTemplate x:DataType="local:Item">
            <muxc:TreeViewItem ItemsSource="{x:Bind Children}"
                               Content="{x:Bind Name}"/>
        </DataTemplate>
    </muxc:TreeView.ItemTemplate>
</muxc:TreeView>

Lihat Tampilan pohon menggunakan pengikatan data untuk kode lengkap.

Item dan kontainer item

Jika Anda menggunakan TreeView.ItemsSource, API ini tersedia untuk mendapatkan node atau item data dari kontainer, dan sebaliknya.

TreeViewItem Deskripsi
TreeView.ItemFromContainer Mendapatkan item data untuk kontainer TreeViewItem yang ditentukan.
TreeView.ContainerFromItem Mendapatkan kontainer TreeViewItem untuk item data yang ditentukan.
TreeViewNode Deskripsi
TreeView.NodeFromContainer Mendapatkan TreeViewNode untuk kontainer TreeViewItem yang ditentukan.
TreeView.ContainerFromNode Mendapatkan kontainer TreeViewItem untuk TreeViewNode yang ditentukan.

Mengelola simpul tampilan pohon

Tampilan pohon ini sama dengan yang dibuat sebelumnya di XAML, tetapi simpul dibuat dalam kode sebagai gantinya.

<muxc:TreeView x:Name="sampleTreeView"/>
private void InitializeTreeView()
{
    muxc.TreeViewNode rootNode = new muxc.TreeViewNode() { Content = "Flavors" };
    rootNode.IsExpanded = true;
    rootNode.Children.Add(new muxc.TreeViewNode() { Content = "Vanilla" });
    rootNode.Children.Add(new muxc.TreeViewNode() { Content = "Strawberry" });
    rootNode.Children.Add(new muxc.TreeViewNode() { Content = "Chocolate" });

    sampleTreeView.RootNodes.Add(rootNode);
}
Private Sub InitializeTreeView()
    Dim rootNode As New muxc.TreeViewNode With {.Content = "Flavors", .IsExpanded = True}
    With rootNode.Children
        .Add(New muxc.TreeViewNode With {.Content = "Vanilla"})
        .Add(New muxc.TreeViewNode With {.Content = "Strawberry"})
        .Add(New muxc.TreeViewNode With {.Content = "Chocolate"})
    End With
    sampleTreeView.RootNodes.Add(rootNode)
End Sub

API ini tersedia untuk mengelola hierarki data tampilan pohon Anda.

Treeview Deskripsi
RootNodes Tampilan pohon dapat memiliki satu atau beberapa simpul akar. Tambahkan objek TreeViewNode ke koleksi RootNodes untuk membuat simpul akar. Induk simpul akar selalu null. Kedalaman simpul akar adalah 0.
TreeViewNode Deskripsi
Anak Tambahkan objek TreeViewNode ke kumpulan Anak dari simpul induk untuk membuat hierarki simpul Anda. Simpul adalah Induk dari semua simpul dalam koleksi Anak-anaknya.
HasChildren true jika simpul telah menyadari anak-anak. false menunjukkan folder kosong atau item.
HasUnrealizedChildren Gunakan properti ini jika Anda mengisi simpul saat diperluas. Lihat Mengisi simpul saat diperluas nanti di artikel ini.
Kedalaman Menunjukkan seberapa jauh dari simpul akar simpul anak.
Orangtua Mendapatkan TreeViewNode yang memiliki koleksi Anak yang merupakan bagian dari simpul ini.

Tampilan pohon menggunakan properti HasChildren dan HasUnrealizedChildren untuk menentukan apakah ikon perluas/ciutkan ditampilkan. Jika salah satu properti benar, ikon ditampilkan; jika tidak, itu tidak ditampilkan.

Konten simpul tampilan pohon

Anda dapat menyimpan item data yang diwakili simpul tampilan pohon di properti Kontennya.

Dalam contoh sebelumnya, konten adalah nilai string sederhana. Di sini, simpul tampilan pohon mewakili folder Gambar pengguna, sehingga pustaka gambar StorageFolder ditetapkan ke properti Konten simpul.

StorageFolder picturesFolder = KnownFolders.PicturesLibrary;
muxc.TreeViewNode pictureNode = new muxc.TreeViewNode();
pictureNode.Content = picturesFolder;
Dim picturesFolder As StorageFolder = KnownFolders.PicturesLibrary
Dim pictureNode As New muxc.TreeViewNode With {.Content = picturesFolder}

Catatan

Untuk mendapatkan akses ke folder Gambar , Anda perlu menentukan kemampuan Pustaka Gambar dalam manifes aplikasi. Lihat Deklarasi kemampuan aplikasi untuk informasi selengkapnya.

Anda dapat menyediakan DataTemplate untuk menentukan bagaimana item data ditampilkan dalam tampilan pohon.

Catatan

Di Windows 10, versi 1803, Anda harus membuat templat ulang kontrol TreeView dan menentukan ItemTemplate kustom jika konten Anda bukan string. Di versi yang lebih baru, atur properti ItemTemplate . Untuk informasi selengkapnya, lihat TreeView.ItemTemplate.

Gaya kontainer item

Baik Anda menggunakan ItemsSource atau RootNodes, elemen aktual yang digunakan untuk menampilkan setiap simpul – yang disebut "kontainer" – adalah objek TreeViewItem . Anda dapat memodifikasi properti TreeViewItem untuk menata kontainer menggunakan properti ItemContainerStyle atau ItemContainerStyleSelector TreeView.

Contoh ini menunjukkan cara mengubah glyph yang diperluas/diciutkan menjadi tanda oranye +/- . Di templat TreeViewItem default, glyph diatur untuk menggunakan Segoe MDL2 Assets font. Anda dapat mengatur properti Setter.Value dengan menyediakan nilai karakter Unicode dalam format yang digunakan oleh XAML, seperti ini: Value="&#xE948;".

<muxc:TreeView>
    <muxc:TreeView.ItemContainerStyle>
        <Style TargetType="muxc:TreeViewItem">
            <Setter Property="CollapsedGlyph" Value="&#xE948;"/>
            <Setter Property="ExpandedGlyph" Value="&#xE949;"/>
            <Setter Property="GlyphBrush" Value="DarkOrange"/>
        </Style>
    </muxc:TreeView.ItemContainerStyle>
    <muxc:TreeView.RootNodes>
        <muxc:TreeViewNode Content="Flavors"
               IsExpanded="True">
            <muxc:TreeViewNode.Children>
                <muxc:TreeViewNode Content="Vanilla"/>
                <muxc:TreeViewNode Content="Strawberry"/>
                <muxc:TreeViewNode Content="Chocolate"/>
            </muxc:TreeViewNode.Children>
        </muxc:TreeViewNode>
    </muxc:TreeView.RootNodes>
</muxc:TreeView>

Pemilih templat item

Secara default, TreeView menunjukkan representasi string item data untuk setiap simpul. Anda dapat mengatur properti ItemTemplate untuk mengubah apa yang ditampilkan untuk semua simpul. Atau, Anda dapat menggunakan ItemTemplateSelector untuk memilih DataTemplate yang berbeda untuk item tampilan pohon berdasarkan jenis item atau beberapa kriteria lain yang Anda tentukan.

Misalnya, di aplikasi penjelajah file, Anda dapat menggunakan satu templat data untuk folder, dan templat lainnya untuk file.

Folders and files using different data templates

Berikut adalah contoh cara membuat dan menggunakan pemilih templat item. Untuk informasi selengkapnya, lihat kelas DataTemplateSelector .

Catatan

Kode ini adalah bagian dari contoh yang lebih besar dan tidak akan berfungsi sendiri. Untuk melihat contoh lengkap, termasuk kode yang menentukan ExplorerItem, lihat repositori Xaml-Controls-Gallery di GitHub. TreeViewPage.xaml dan TreeViewPage.xaml.cs berisi kode yang relevan.

<Page.Resources>
    <DataTemplate x:Key="FolderTemplate" x:DataType="local:ExplorerItem">
        <muxc:TreeViewItem ItemsSource="{x:Bind Children}">
            <StackPanel Orientation="Horizontal">
                <Image Width="20" Source="Assets/folder.png"/>
                <TextBlock Text="{x:Bind Name}" />
            </StackPanel>
        </muxc:TreeViewItem>
    </DataTemplate>

    <DataTemplate x:Key="FileTemplate" x:DataType="local:ExplorerItem">
        <muxc:TreeViewItem>
            <StackPanel Orientation="Horizontal">
                <Image Width="20" Source="Assets/file.png"/>
                <TextBlock Text="{x:Bind Name}"/>
            </StackPanel>
        </muxc:TreeViewItem>
    </DataTemplate>

    <local:ExplorerItemTemplateSelector
            x:Key="ExplorerItemTemplateSelector"
            FolderTemplate="{StaticResource FolderTemplate}"
            FileTemplate="{StaticResource FileTemplate}" />
</Page.Resources>

<Grid>
    <muxc:TreeView
        ItemsSource="{x:Bind DataSource}"
        ItemTemplateSelector="{StaticResource ExplorerItemTemplateSelector}"/>
</Grid>
public class ExplorerItemTemplateSelector : DataTemplateSelector
{
    public DataTemplate FolderTemplate { get; set; }
    public DataTemplate FileTemplate { get; set; }

    protected override DataTemplate SelectTemplateCore(object item)
    {
        var explorerItem = (ExplorerItem)item;
        if (explorerItem.Type == ExplorerItem.ExplorerItemType.Folder) return FolderTemplate;

        return FileTemplate;
    }
}

Jenis objek yang diteruskan ke metode SelectTemplateCore bergantung pada apakah Anda membuat tampilan pohon dengan mengatur properti ItemsSource , atau dengan membuat dan mengelola objek TreeViewNode sendiri.

  • Jika ItemsSource diatur, objek akan menjadi tipe item data apa pun. Dalam contoh sebelumnya, objek adalah ExplorerItem, sehingga dapat digunakan setelah cast sederhana ke ExplorerItem: var explorerItem = (ExplorerItem)item;.
  • Jika ItemsSource tidak diatur dan Anda mengelola simpul tampilan pohon sendiri, objek yang diteruskan ke SelectTemplateCore adalah TreeViewNode. Dalam hal ini, Anda bisa mendapatkan item data dari properti TreeViewNode.Content .

Berikut adalah pemilih templat data dari contoh tampilan pohon pustaka Gambar dan Musik yang ditampilkan nanti. Metode SelectTemplateCore menerima TreeViewNode, yang mungkin memiliki StorageFolder atau StorageFile sebagai kontennya. Berdasarkan konten, Anda dapat mengembalikan templat default, atau templat tertentu untuk folder musik, folder gambar, file musik, atau file gambar.

protected override DataTemplate SelectTemplateCore(object item)
{
    var node = (TreeViewNode)item;
    if (node.Content is StorageFolder)
    {
        var content = node.Content as StorageFolder;
        if (content.DisplayName.StartsWith("Pictures")) return PictureFolderTemplate;
        if (content.DisplayName.StartsWith("Music")) return MusicFolderTemplate;
    }
    else if (node.Content is StorageFile)
    {
        var content = node.Content as StorageFile;
        if (content.ContentType.StartsWith("image")) return PictureItemTemplate;
        if (content.ContentType.StartsWith("audio")) return MusicItemTemplate;
    }
    return DefaultTemplate;
}
Protected Overrides Function SelectTemplateCore(ByVal item As Object) As DataTemplate
    Dim node = CType(item, muxc.TreeViewNode)

    If TypeOf node.Content Is StorageFolder Then
        Dim content = TryCast(node.Content, StorageFolder)
        If content.DisplayName.StartsWith("Pictures") Then Return PictureFolderTemplate
        If content.DisplayName.StartsWith("Music") Then Return MusicFolderTemplate
    ElseIf TypeOf node.Content Is StorageFile Then
        Dim content = TryCast(node.Content, StorageFile)
        If content.ContentType.StartsWith("image") Then Return PictureItemTemplate
        If content.ContentType.StartsWith("audio") Then Return MusicItemTemplate
    End If

    Return DefaultTemplate
End Function

Berinteraksi dengan tampilan pohon

Anda dapat mengonfigurasi tampilan pohon untuk memungkinkan pengguna berinteraksi dengannya dengan beberapa cara berbeda:

  • Memperluas atau menciutkan simpul
  • Item pilihan tunggal atau multi-pilih
  • Klik untuk memanggil item

Perluas/ciutkan

Setiap simpul tampilan pohon yang memiliki anak selalu dapat diperluas atau diciutkan dengan mengklik lampirkan/ciutkan glyph. Anda juga dapat memperluas atau menciutkan simpul secara terprogram, dan merespons saat node berubah status.

Memperluas/menciutkan simpul secara terprogram

Ada 2 cara untuk memperluas atau menciutkan simpul tampilan pohon dalam kode Anda.

  • Kelas TreeView memiliki metode Ciutkan dan Perluas . Saat Anda memanggil metode ini, Anda meneruskan TreeViewNode yang ingin Anda perluas atau ciutkan.

  • Setiap TreeViewNode memiliki properti IsExpanded . Anda dapat menggunakan properti ini untuk memeriksa status simpul, atau mengaturnya untuk mengubah status. Anda juga dapat mengatur properti ini di XAML untuk mengatur status awal simpul.

Mengisi simpul saat diperluas

Anda mungkin perlu menunjukkan sejumlah besar simpul dalam tampilan pohon Anda, atau Anda mungkin tidak tahu sebelumnya berapa banyak simpul yang akan dimilikinya. Kontrol TreeView tidak divirtualisasi, sehingga Anda dapat mengelola sumber daya dengan mengisi setiap simpul saat diperluas, dan menghapus simpul anak saat diciutkan.

Tangani peristiwa Perluas dan gunakan properti HasUnrealizedChildren untuk menambahkan anak ke simpul saat sedang diperluas. Properti HasUnrealizedChildren menunjukkan apakah simpul perlu diisi, atau jika koleksi Anak-anaknya telah diisi. Penting untuk diingat bahwa TreeViewNode tidak mengatur nilai ini, Anda perlu mengelolanya di kode aplikasi Anda.

Berikut adalah contoh API ini yang digunakan. Lihat contoh kode lengkap di akhir artikel ini untuk konteks, termasuk implementasi FillTreeNode.

private void SampleTreeView_Expanding(muxc.TreeView sender, muxc.TreeViewExpandingEventArgs args)
{
    if (args.Node.HasUnrealizedChildren)
    {
        FillTreeNode(args.Node);
    }
}
Private Sub SampleTreeView_Expanding(sender As muxc.TreeView, args As muxc.TreeViewExpandingEventArgs)
    If args.Node.HasUnrealizedChildren Then
        FillTreeNode(args.Node)
    End If
End Sub

Ini tidak diperlukan, tetapi Anda mungkin juga ingin menangani peristiwa Yang Diciutkan dan menghapus simpul anak saat simpul induk ditutup. Ini bisa menjadi penting jika tampilan pohon Anda memiliki banyak simpul, atau jika data simpul menggunakan banyak sumber daya. Anda harus mempertimbangkan dampak performa mengisi simpul setiap kali dibuka versus meninggalkan anak-anak pada simpul tertutup. Opsi terbaik akan bergantung pada aplikasi Anda.

Berikut adalah contoh handler untuk peristiwa Diciutkan .

private void SampleTreeView_Collapsed(muxc.TreeView sender, muxc.TreeViewCollapsedEventArgs args)
{
    args.Node.Children.Clear();
    args.Node.HasUnrealizedChildren = true;
}
Private Sub SampleTreeView_Collapsed(sender As muxc.TreeView, args As muxc.TreeViewCollapsedEventArgs)
    args.Node.Children.Clear()
    args.Node.HasUnrealizedChildren = True
End Sub

Memanggil item

Pengguna dapat memanggil tindakan (memperlakukan item seperti tombol) alih-alih memilih item. Anda menangani peristiwa ItemInvoked untuk merespons interaksi pengguna ini.

Catatan

Tidak seperti ListView, yang memiliki properti IsItemClickEnabled , memanggil item selalu diaktifkan pada tampilan pohon. Anda masih dapat memilih apakah akan menangani peristiwa atau tidak.

Kelas TreeViewItemInvokedEventArgs

Arg peristiwa ItemInvoked memberi Anda akses ke item yang dipanggil. Properti InvokedItem memiliki simpul yang dipanggil. Anda dapat melemparkannya ke TreeViewNode dan mendapatkan item data dari properti TreeViewNode.Content .

Berikut adalah contoh penanganan aktivitas ItemInvoked . Item data adalah IStorageItem, dan contoh ini hanya menampilkan beberapa info tentang file dan pohon. Selain itu, jika simpul adalah node folder, node akan memperluas atau menciutkan simpul secara bersamaan. Jika tidak, simpul diperluas atau diciutkan hanya ketika chevron diklik.

private void SampleTreeView_ItemInvoked(muxc.TreeView sender, muxc.TreeViewItemInvokedEventArgs args)
{
    var node = args.InvokedItem as muxc.TreeViewNode;
    if (node.Content is IStorageItem item)
    {
        FileNameTextBlock.Text = item.Name;
        FilePathTextBlock.Text = item.Path;
        TreeDepthTextBlock.Text = node.Depth.ToString();

        if (node.Content is StorageFolder)
        {
            node.IsExpanded = !node.IsExpanded;
        }
    }
}
Private Sub SampleTreeView_ItemInvoked(sender As muxc.TreeView, args As muxc.TreeViewItemInvokedEventArgs)
    Dim node = TryCast(args.InvokedItem, muxc.TreeViewNode)
    Dim item = TryCast(node.Content, IStorageItem)
    If item IsNot Nothing Then
        FileNameTextBlock.Text = item.Name
        FilePathTextBlock.Text = item.Path
        TreeDepthTextBlock.Text = node.Depth.ToString()
        If TypeOf node.Content Is StorageFolder Then
            node.IsExpanded = Not node.IsExpanded
        End If
    End If
End Sub

Pilihan item

Kontrol TreeView mendukung pilihan tunggal dan multi-pilihan. Secara default, pemilihan simpul dinonaktifkan, tetapi Anda dapat mengatur properti TreeView.SelectionMode untuk memungkinkan pemilihan simpul. Nilai TreeViewSelectionMode adalah None, Single, dan Multiple.

Beberapa pilihan

Saat beberapa pilihan diaktifkan, kotak centang diperlihatkan di samping setiap simpul tampilan pohon, dan item yang dipilih disorot. Pengguna dapat memilih atau membatalkan pilih item dengan menggunakan kotak centang; mengklik item masih menyebabkannya dipanggil.

Memilih atau membatalkan pemilihan simpul induk akan memilih atau membatalkan pilih semua anak di bawah simpul tersebut. Jika beberapa, tetapi tidak semua, dari turunan di bawah simpul induk dipilih, kotak centang untuk simpul induk ditampilkan dalam status tidak ditentukan.

Multiple selection in a tree view

Simpul yang dipilih ditambahkan ke koleksi SelectedNodes tampilan pohon. Anda dapat memanggil metode SelectAll untuk memilih semua simpul dalam tampilan pohon.

Catatan

Jika Anda memanggil SelectAll, semua simpul yang terealisasi dipilih, terlepas dari SelectionMode. Untuk memberikan pengalaman pengguna yang konsisten, Anda hanya boleh memanggil SelectAll jika SelectionMode adalah Multiple.

Pemilihan dan node yang direalisasi/tidak direalisasi

Jika tampilan pohon Anda memiliki simpul yang belum direalisasi, mereka tidak diperhitungkan untuk pemilihan. Berikut adalah beberapa hal yang perlu Anda ingat mengenai pemilihan dengan simpul yang tidak direalisasi.

  • Jika pengguna memilih simpul induk, semua anak yang direalisasikan di bawah induk tersebut juga dipilih. Demikian pula, jika semua simpul anak dipilih, simpul induk juga dipilih.
  • Metode SelectAll hanya menambahkan simpul yang direalisasikan ke koleksi SelectedNodes .
  • Jika simpul induk dengan anak yang tidak direalisasi dipilih, anak-anak akan dipilih saat mereka direalisasikan.

SelectedItem/SelectedItems

TreeView memiliki properti SelectedItem dan SelectedItems . Anda dapat menggunakan properti ini untuk mendapatkan konten simpul yang dipilih secara langsung. Jika beberapa pilihan diaktifkan, SelectedItem berisi item pertama dalam koleksi SelectedItems.

SelectionChanged

Anda dapat menangani peristiwa SelectionChanged untuk merespons saat kumpulan item yang dipilih berubah, baik secara terprogram atau melalui interaksi pengguna.

<TreeView ItemsSource="{x:Bind Folders}"
          SelectionMode="Multiple"
          SelectionChanged="TreeView_SelectionChanged"/>
public void TreeView_SelectionChanged(TreeView sender, TreeViewSelectionChangedEventArgs args)
{
    foreach (object item in args.RemovedItems)
    {
        this.SelectedFolders.Remove((Folder)item);
    }

    foreach (object item in args.AddedItems)
    {
        this.SelectedFolders.Add((Folder)item);
    }
}

Contoh kode

Contoh kode berikut menunjukkan berbagai fitur kontrol tampilan pohon.

Tampilan pohon menggunakan XAML

Contoh ini menunjukkan cara membuat struktur tampilan pohon sederhana di XAML. Tampilan pohon menunjukkan rasa es krim dan topping yang dapat dipilih pengguna, disusun dalam kategori. Multi-pilihan diaktifkan, dan ketika pengguna mengklik tombol, item yang dipilih ditampilkan di antarmuka pengguna aplikasi utama.

<Page
    x:Class="TreeViewTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
          Padding="100">
        <SplitView IsPaneOpen="True"
               DisplayMode="Inline"
               OpenPaneLength="296">
            <SplitView.Pane>
                <muxc:TreeView x:Name="DessertTree" SelectionMode="Multiple">
                    <muxc:TreeView.RootNodes>
                        <muxc:TreeViewNode Content="Flavors" IsExpanded="True">
                            <muxc:TreeViewNode.Children>
                                <muxc:TreeViewNode Content="Vanilla"/>
                                <muxc:TreeViewNode Content="Strawberry"/>
                                <muxc:TreeViewNode Content="Chocolate"/>
                            </muxc:TreeViewNode.Children>
                        </muxc:TreeViewNode>

                        <muxc:TreeViewNode Content="Toppings">
                            <muxc:TreeViewNode.Children>
                                <muxc:TreeViewNode Content="Candy">
                                    <muxc:TreeViewNode.Children>
                                        <muxc:TreeViewNode Content="Chocolate"/>
                                        <muxc:TreeViewNode Content="Mint"/>
                                        <muxc:TreeViewNode Content="Sprinkles"/>
                                    </muxc:TreeViewNode.Children>
                                </muxc:TreeViewNode>
                                <muxc:TreeViewNode Content="Fruits">
                                    <muxc:TreeViewNode.Children>
                                        <muxc:TreeViewNode Content="Mango"/>
                                        <muxc:TreeViewNode Content="Peach"/>
                                        <muxc:TreeViewNode Content="Kiwi"/>
                                    </muxc:TreeViewNode.Children>
                                </muxc:TreeViewNode>
                                <muxc:TreeViewNode Content="Berries">
                                    <muxc:TreeViewNode.Children>
                                        <muxc:TreeViewNode Content="Strawberry"/>
                                        <muxc:TreeViewNode Content="Blueberry"/>
                                        <muxc:TreeViewNode Content="Blackberry"/>
                                    </muxc:TreeViewNode.Children>
                                </muxc:TreeViewNode>
                            </muxc:TreeViewNode.Children>
                        </muxc:TreeViewNode>
                    </muxc:TreeView.RootNodes>
                </muxc:TreeView>
            </SplitView.Pane>

            <StackPanel Grid.Column="1" Margin="12,0">
                <Button Content="Select all" Click="SelectAllButton_Click"/>
                <Button Content="Create order" Click="OrderButton_Click" Margin="0,12"/>
                <TextBlock Text="Your flavor selections:" Style="{StaticResource CaptionTextBlockStyle}"/>
                <TextBlock x:Name="FlavorList" Margin="0,0,0,12"/>
                <TextBlock Text="Your topping selections:" Style="{StaticResource CaptionTextBlockStyle}"/>
                <TextBlock x:Name="ToppingList"/>
            </StackPanel>
        </SplitView>
    </Grid>
</Page>
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using muxc = Microsoft.UI.Xaml.Controls;

namespace TreeViewTest
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        private void OrderButton_Click(object sender, RoutedEventArgs e)
        {
            FlavorList.Text = string.Empty;
            ToppingList.Text = string.Empty;

            foreach (muxc.TreeViewNode node in DessertTree.SelectedNodes)
            {
                if (node.Parent.Content?.ToString() == "Flavors")
                {
                    FlavorList.Text += node.Content + "; ";
                }
                else if (node.HasChildren == false)
                {
                    ToppingList.Text += node.Content + "; ";
                }
            }
        }

        private void SelectAllButton_Click(object sender, RoutedEventArgs e)
        {
            if (DessertTree.SelectionMode == muxc.TreeViewSelectionMode.Multiple)
            {
                DessertTree.SelectAll();
            }
        }
    }
}
Private Sub OrderButton_Click(sender As Object, e As RoutedEventArgs)
    FlavorList.Text = String.Empty
    ToppingList.Text = String.Empty
    For Each node As muxc.TreeViewNode In DessertTree.SelectedNodes
        If node.Parent.Content?.ToString() = "Flavors" Then
            FlavorList.Text += node.Content & "; "
        ElseIf node.HasChildren = False Then
            ToppingList.Text += node.Content & "; "
        End If
    Next
End Sub

Private Sub SelectAllButton_Click(sender As Object, e As RoutedEventArgs)
    If DessertTree.SelectionMode = muxc.TreeViewSelectionMode.Multiple Then
        DessertTree.SelectAll()
    End If
End Sub

Tampilan pohon menggunakan pengikatan data

Contoh ini menunjukkan cara membuat tampilan pohon yang sama dengan contoh sebelumnya. Namun, alih-alih membuat hierarki data di XAML, data dibuat dalam kode dan terikat ke properti ItemsSource tampilan pohon. (Penanganan aktivitas tombol yang ditampilkan dalam contoh sebelumnya juga berlaku untuk contoh ini.)

<Page
    x:Class="TreeViewTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
    xmlns:local="using:TreeViewTest"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
          Padding="100">
        <SplitView IsPaneOpen="True"
                   DisplayMode="Inline"
                   OpenPaneLength="296">
            <SplitView.Pane>
                <muxc:TreeView Name="DessertTree"
                                      SelectionMode="Multiple"
                                      ItemsSource="{x:Bind DataSource}">
                    <muxc:TreeView.ItemTemplate>
                        <DataTemplate x:DataType="local:Item">
                            <muxc:TreeViewItem
                                ItemsSource="{x:Bind Children}"
                                Content="{x:Bind Name}"/>
                        </DataTemplate>
                    </muxc:TreeView.ItemTemplate>
                </muxc:TreeView>
            </SplitView.Pane>

            <StackPanel Grid.Column="1" Margin="12,0">
                <Button Content="Select all"
                        Click="SelectAllButton_Click"/>
                <Button Content="Create order"
                        Click="OrderButton_Click"
                        Margin="0,12"/>
                <TextBlock Text="Your flavor selections:"
                           Style="{StaticResource CaptionTextBlockStyle}"/>
                <TextBlock x:Name="FlavorList" Margin="0,0,0,12"/>
                <TextBlock Text="Your topping selections:"
                           Style="{StaticResource CaptionTextBlockStyle}"/>
                <TextBlock x:Name="ToppingList"/>
            </StackPanel>
        </SplitView>
    </Grid>

</Page>
using System.Collections.ObjectModel;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using muxc = Microsoft.UI.Xaml.Controls;

namespace TreeViewTest
{
    public sealed partial class MainPage : Page
    {
        private ObservableCollection<Item> DataSource = new ObservableCollection<Item>();

        public MainPage()
        {
            this.InitializeComponent();
            DataSource = GetDessertData();
        }

        private ObservableCollection<Item> GetDessertData()
        {
            var list = new ObservableCollection<Item>();

            Item flavorsCategory = new Item()
            {
                Name = "Flavors",
                Children =
                {
                    new Item() { Name = "Vanilla" },
                    new Item() { Name = "Strawberry" },
                    new Item() { Name = "Chocolate" }
                }
            };

            Item toppingsCategory = new Item()
            {
                Name = "Toppings",
                Children =
                {
                    new Item()
                    {
                        Name = "Candy",
                        Children =
                        {
                            new Item() { Name = "Chocolate" },
                            new Item() { Name = "Mint" },
                            new Item() { Name = "Sprinkles" }
                        }
                    },
                    new Item()
                    {
                        Name = "Fruits",
                        Children =
                        {
                            new Item() { Name = "Mango" },
                            new Item() { Name = "Peach" },
                            new Item() { Name = "Kiwi" }
                        }
                    },
                    new Item()
                    {
                        Name = "Berries",
                        Children =
                        {
                            new Item() { Name = "Strawberry" },
                            new Item() { Name = "Blueberry" },
                            new Item() { Name = "Blackberry" }
                        }
                    }
                }
            };

            list.Add(flavorsCategory);
            list.Add(toppingsCategory);
            return list;
        }

        private void OrderButton_Click(object sender, RoutedEventArgs e)
        {
            FlavorList.Text = string.Empty;
            ToppingList.Text = string.Empty;

            foreach (muxc.TreeViewNode node in DessertTree.SelectedNodes)
            {
                if (node.Parent.Content?.ToString() == "Flavors")
                {
                    FlavorList.Text += node.Content + "; ";
                }
                else if (node.HasChildren == false)
                {
                    ToppingList.Text += node.Content + "; ";
                }
            }
        }

        private void SelectAllButton_Click(object sender, RoutedEventArgs e)
        {
            if (DessertTree.SelectionMode == muxc.TreeViewSelectionMode.Multiple)
            {
                DessertTree.SelectAll();
            }
        }
    }

    public class Item
    {
        public string Name { get; set; }
        public ObservableCollection<Item> Children { get; set; } = new ObservableCollection<Item>();

        public override string ToString()
        {
            return Name;
        }
    }
}

Tampilan pohon pustaka Gambar dan Musik

Contoh ini memperlihatkan cara membuat tampilan pohon yang memperlihatkan konten dan struktur pustaka Gambar dan Musik pengguna. Jumlah item tidak dapat diketahui sebelumnya, sehingga setiap simpul diisi saat diperluas, dan dikosongkan saat diciutkan.

Templat item kustom digunakan untuk menampilkan item data, yang berjenis IStorageItem.

Penting

Kode dalam contoh ini memerlukan kemampuan picturesLibrary dan musicLibrary . Untuk informasi selengkapnya tentang akses file, lihat Izin akses file, Menghitung dan mengkueri file dan folder, serta File dan folder di pustaka Musik, Gambar, dan Video.

<Page
    x:Class="TreeViewTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TreeViewTest"
    xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
    xmlns:storage="using:Windows.Storage"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Page.Resources>
        <DataTemplate x:Key="TreeViewItemDataTemplate" x:DataType="muxc:TreeViewNode">
            <Grid Height="44">
                <TextBlock Text="{x:Bind ((storage:IStorageItem)Content).Name}"
                           HorizontalAlignment="Left"
                           VerticalAlignment="Center"
                           Style="{ThemeResource BodyTextBlockStyle}"/>
            </Grid>
        </DataTemplate>

        <DataTemplate x:Key="MusicItemDataTemplate" x:DataType="muxc:TreeViewNode">
            <StackPanel Height="44" Orientation="Horizontal">
                <SymbolIcon Symbol="Audio" Margin="0,0,4,0"/>
                <TextBlock Text="{x:Bind ((storage:StorageFile)Content).DisplayName}"
                           HorizontalAlignment="Left"
                           VerticalAlignment="Center"
                           Style="{ThemeResource BodyTextBlockStyle}"/>
            </StackPanel>
        </DataTemplate>

        <DataTemplate x:Key="PictureItemDataTemplate" x:DataType="muxc:TreeViewNode">
            <StackPanel Height="44" Orientation="Horizontal">
                <FontIcon FontFamily="Segoe MDL2 Assets" Glyph="&#xEB9F;"
                          Margin="0,0,4,0"/>
                <TextBlock Text="{x:Bind ((storage:StorageFile)Content).DisplayName}"
                           HorizontalAlignment="Left"
                           VerticalAlignment="Center"
                           Style="{ThemeResource BodyTextBlockStyle}"/>
            </StackPanel>
        </DataTemplate>

        <DataTemplate x:Key="MusicFolderDataTemplate" x:DataType="muxc:TreeViewNode">
            <StackPanel Height="44" Orientation="Horizontal">
                <SymbolIcon Symbol="MusicInfo" Margin="0,0,4,0"/>
                <TextBlock Text="{x:Bind ((storage:StorageFolder)Content).DisplayName}"
                           HorizontalAlignment="Left"
                           VerticalAlignment="Center"
                           Style="{ThemeResource BodyTextBlockStyle}"/>
            </StackPanel>
        </DataTemplate>

        <DataTemplate x:Key="PictureFolderDataTemplate" x:DataType="muxc:TreeViewNode">
            <StackPanel Height="44" Orientation="Horizontal">
                <SymbolIcon Symbol="Pictures" Margin="0,0,4,0"/>
                <TextBlock Text="{x:Bind ((storage:StorageFolder)Content).DisplayName}"
                           HorizontalAlignment="Left"
                           VerticalAlignment="Center"
                           Style="{ThemeResource BodyTextBlockStyle}"/>
            </StackPanel>
        </DataTemplate>

        <local:ExplorerItemTemplateSelector
            x:Key="ExplorerItemTemplateSelector"
            DefaultTemplate="{StaticResource TreeViewItemDataTemplate}"
            MusicItemTemplate="{StaticResource MusicItemDataTemplate}"
            MusicFolderTemplate="{StaticResource MusicFolderDataTemplate}"
            PictureItemTemplate="{StaticResource PictureItemDataTemplate}"
            PictureFolderTemplate="{StaticResource PictureFolderDataTemplate}"/>
    </Page.Resources>

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <SplitView IsPaneOpen="True"
                   DisplayMode="Inline"
                   OpenPaneLength="296">
            <SplitView.Pane>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <Button Content="Refresh tree" Click="RefreshButton_Click" Margin="24,12"/>
                    <muxc:TreeView x:Name="sampleTreeView" Grid.Row="1" SelectionMode="Single"
                              ItemTemplateSelector="{StaticResource ExplorerItemTemplateSelector}"
                              Expanding="SampleTreeView_Expanding"
                              Collapsed="SampleTreeView_Collapsed"
                              ItemInvoked="SampleTreeView_ItemInvoked"/>
                </Grid>
            </SplitView.Pane>

            <StackPanel Grid.Column="1" Margin="12,72">
                <TextBlock Text="File name:" Style="{StaticResource CaptionTextBlockStyle}"/>
                <TextBlock x:Name="FileNameTextBlock" Margin="0,0,0,12"/>

                <TextBlock Text="File path:" Style="{StaticResource CaptionTextBlockStyle}"/>
                <TextBlock x:Name="FilePathTextBlock" Margin="0,0,0,12"/>

                <TextBlock Text="Tree depth:" Style="{StaticResource CaptionTextBlockStyle}"/>
                <TextBlock x:Name="TreeDepthTextBlock" Margin="0,0,0,12"/>
            </StackPanel>
        </SplitView>
    </Grid>
</Page>
using System;
using System.Collections.Generic;
using Windows.Storage;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using muxc = Microsoft.UI.Xaml.Controls;

namespace TreeViewTest
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            InitializeTreeView();
        }

        private void InitializeTreeView()
        {
            // A TreeView can have more than 1 root node. The Pictures library
            // and the Music library will each be a root node in the tree.
            // Get Pictures library.
            StorageFolder picturesFolder = KnownFolders.PicturesLibrary;
            muxc.TreeViewNode pictureNode = new muxc.TreeViewNode();
            pictureNode.Content = picturesFolder;
            pictureNode.IsExpanded = true;
            pictureNode.HasUnrealizedChildren = true;
            sampleTreeView.RootNodes.Add(pictureNode);
            FillTreeNode(pictureNode);

            // Get Music library.
            StorageFolder musicFolder = KnownFolders.MusicLibrary;
            muxc.TreeViewNode musicNode = new muxc.TreeViewNode();
            musicNode.Content = musicFolder;
            musicNode.IsExpanded = true;
            musicNode.HasUnrealizedChildren = true;
            sampleTreeView.RootNodes.Add(musicNode);
            FillTreeNode(musicNode);
        }

        private async void FillTreeNode(muxc.TreeViewNode node)
        {
            // Get the contents of the folder represented by the current tree node.
            // Add each item as a new child node of the node that's being expanded.

            // Only process the node if it's a folder and has unrealized children.
            StorageFolder folder = null;

            if (node.Content is StorageFolder && node.HasUnrealizedChildren == true)
            {
                folder = node.Content as StorageFolder;
            }
            else
            {
                // The node isn't a folder, or it's already been filled.
                return;
            }

            IReadOnlyList<IStorageItem> itemsList = await folder.GetItemsAsync();

            if (itemsList.Count == 0)
            {
                // The item is a folder, but it's empty. Leave HasUnrealizedChildren = true so
                // that the chevron appears, but don't try to process children that aren't there.
                return;
            }

            foreach (var item in itemsList)
            {
                var newNode = new muxc.TreeViewNode();
                newNode.Content = item;

                if (item is StorageFolder)
                {
                    // If the item is a folder, set HasUnrealizedChildren to true.
                    // This makes the collapsed chevron show up.
                    newNode.HasUnrealizedChildren = true;
                }
                else
                {
                    // Item is StorageFile. No processing needed for this scenario.
                }

                node.Children.Add(newNode);
            }

            // Children were just added to this node, so set HasUnrealizedChildren to false.
            node.HasUnrealizedChildren = false;
        }

        private void SampleTreeView_Expanding(muxc.TreeView sender, muxc.TreeViewExpandingEventArgs args)
        {
            if (args.Node.HasUnrealizedChildren)
            {
                FillTreeNode(args.Node);
            }
        }

        private void SampleTreeView_Collapsed(muxc.TreeView sender, muxc.TreeViewCollapsedEventArgs args)
        {
            args.Node.Children.Clear();
            args.Node.HasUnrealizedChildren = true;
        }

        private void SampleTreeView_ItemInvoked(muxc.TreeView sender, muxc.TreeViewItemInvokedEventArgs args)
        {
            var node = args.InvokedItem as muxc.TreeViewNode;

            if (node.Content is IStorageItem item)
            {
                FileNameTextBlock.Text = item.Name;
                FilePathTextBlock.Text = item.Path;
                TreeDepthTextBlock.Text = node.Depth.ToString();

                if (node.Content is StorageFolder)
                {
                    node.IsExpanded = !node.IsExpanded;
                }
            }
        }

        private void RefreshButton_Click(object sender, RoutedEventArgs e)
        {
            sampleTreeView.RootNodes.Clear();
            InitializeTreeView();
        }
    }

    public class ExplorerItemTemplateSelector : DataTemplateSelector
    {
        public DataTemplate DefaultTemplate { get; set; }
        public DataTemplate MusicItemTemplate { get; set; }
        public DataTemplate PictureItemTemplate { get; set; }
        public DataTemplate MusicFolderTemplate { get; set; }
        public DataTemplate PictureFolderTemplate { get; set; }

        protected override DataTemplate SelectTemplateCore(object item)
        {
            var node = (muxc.TreeViewNode)item;

            if (node.Content is StorageFolder)
            {
                var content = node.Content as StorageFolder;
                if (content.DisplayName.StartsWith("Pictures")) return PictureFolderTemplate;
                if (content.DisplayName.StartsWith("Music")) return MusicFolderTemplate;
            }
            else if (node.Content is StorageFile)
            {
                var content = node.Content as StorageFile;
                if (content.ContentType.StartsWith("image")) return PictureItemTemplate;
                if (content.ContentType.StartsWith("audio")) return MusicItemTemplate;

            }
            return DefaultTemplate;
        }
    }
}
Public NotInheritable Class MainPage
    Inherits Page

    Public Sub New()
        InitializeComponent()
        InitializeTreeView()
    End Sub

    Private Sub InitializeTreeView()
        ' A TreeView can have more than 1 root node. The Pictures library
        ' and the Music library will each be a root node in the tree.
        ' Get Pictures library.
        Dim picturesFolder As StorageFolder = KnownFolders.PicturesLibrary
        Dim pictureNode As New muxc.TreeViewNode With {
        .Content = picturesFolder,
        .IsExpanded = True,
        .HasUnrealizedChildren = True
    }
        sampleTreeView.RootNodes.Add(pictureNode)
        FillTreeNode(pictureNode)

        ' Get Music library.
        Dim musicFolder As StorageFolder = KnownFolders.MusicLibrary
        Dim musicNode As New muxc.TreeViewNode With {
        .Content = musicFolder,
        .IsExpanded = True,
        .HasUnrealizedChildren = True
    }
        sampleTreeView.RootNodes.Add(musicNode)
        FillTreeNode(musicNode)
    End Sub

    Private Async Sub FillTreeNode(node As muxc.TreeViewNode)
        ' Get the contents of the folder represented by the current tree node.
        ' Add each item as a new child node of the node that's being expanded.

        ' Only process the node if it's a folder and has unrealized children.
        Dim folder As StorageFolder = Nothing
        If TypeOf node.Content Is StorageFolder AndAlso node.HasUnrealizedChildren Then
            folder = TryCast(node.Content, StorageFolder)
        Else
            ' The node isn't a folder, or it's already been filled.
            Return
        End If

        Dim itemsList As IReadOnlyList(Of IStorageItem) = Await folder.GetItemsAsync()
        If itemsList.Count = 0 Then
            ' The item is a folder, but it's empty. Leave HasUnrealizedChildren = true so
            ' that the chevron appears, but don't try to process children that aren't there.
            Return
        End If

        For Each item In itemsList
            Dim newNode As New muxc.TreeViewNode With {
            .Content = item
        }
            If TypeOf item Is StorageFolder Then
                ' If the item is a folder, set HasUnrealizedChildren to True.
                ' This makes the collapsed chevron show up.
                newNode.HasUnrealizedChildren = True
            Else
                ' Item is StorageFile. No processing needed for this scenario.
            End If
            node.Children.Add(newNode)
        Next

        ' Children were just added to this node, so set HasUnrealizedChildren to False.
        node.HasUnrealizedChildren = False
    End Sub

    Private Sub SampleTreeView_Expanding(sender As muxc.TreeView, args As muxc.TreeViewExpandingEventArgs)
        If args.Node.HasUnrealizedChildren Then
            FillTreeNode(args.Node)
        End If
    End Sub

    Private Sub SampleTreeView_Collapsed(sender As muxc.TreeView, args As muxc.TreeViewCollapsedEventArgs)
        args.Node.Children.Clear()
        args.Node.HasUnrealizedChildren = True
    End Sub

    Private Sub SampleTreeView_ItemInvoked(sender As muxc.TreeView, args As muxc.TreeViewItemInvokedEventArgs)
        Dim node = TryCast(args.InvokedItem, muxc.TreeViewNode)
        Dim item = TryCast(node.Content, IStorageItem)
        If item IsNot Nothing Then
            FileNameTextBlock.Text = item.Name
            FilePathTextBlock.Text = item.Path
            TreeDepthTextBlock.Text = node.Depth.ToString()
            If TypeOf node.Content Is StorageFolder Then
                node.IsExpanded = Not node.IsExpanded
            End If
        End If
    End Sub

    Private Sub RefreshButton_Click(sender As Object, e As RoutedEventArgs)
        sampleTreeView.RootNodes.Clear()
        InitializeTreeView()
    End Sub

End Class

Public Class ExplorerItemTemplateSelector
    Inherits DataTemplateSelector

    Public Property DefaultTemplate As DataTemplate
    Public Property MusicItemTemplate As DataTemplate
    Public Property PictureItemTemplate As DataTemplate
    Public Property MusicFolderTemplate As DataTemplate
    Public Property PictureFolderTemplate As DataTemplate

    Protected Overrides Function SelectTemplateCore(ByVal item As Object) As DataTemplate
        Dim node = CType(item, muxc.TreeViewNode)

        If TypeOf node.Content Is StorageFolder Then
            Dim content = TryCast(node.Content, StorageFolder)
            If content.DisplayName.StartsWith("Pictures") Then Return PictureFolderTemplate
            If content.DisplayName.StartsWith("Music") Then Return MusicFolderTemplate
        ElseIf TypeOf node.Content Is StorageFile Then
            Dim content = TryCast(node.Content, StorageFile)
            If content.ContentType.StartsWith("image") Then Return PictureItemTemplate
            If content.ContentType.StartsWith("audio") Then Return MusicItemTemplate
        End If

        Return DefaultTemplate
    End Function
End Class

Seret dan letakkan item di antara tampilan pohon

Contoh berikut menunjukkan cara membuat dua tampilan pohon yang itemnya dapat diseret dan dihilangkan satu sama lain. Saat item diseret ke tampilan pohon lainnya, item ditambahkan ke akhir daftar. Namun, item dapat diurutkan kembali dalam tampilan pohon. Contoh ini juga hanya memperhitungkan tampilan pohon dengan satu simpul akar.

<Page
    x:Class="TreeViewTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <TreeView x:Name="treeView1"
                  AllowDrop="True"
                  CanDragItems="True"
                  CanReorderItems="True"
                  DragOver="TreeView_DragOver"
                  Drop="TreeView_Drop"
                  DragItemsStarting="TreeView_DragItemsStarting"
                  DragItemsCompleted="TreeView_DragItemsCompleted"/>
        <TreeView x:Name="treeView2"
                  AllowDrop="True"
                  Grid.Column="1"
                  CanDragItems="True"
                  CanReorderItems="True"
                  DragOver="TreeView_DragOver"
                  Drop="TreeView_Drop"
                  DragItemsStarting="TreeView_DragItemsStarting"
                  DragItemsCompleted="TreeView_DragItemsCompleted"/>

    </Grid>

</Page>
using System;
using Windows.ApplicationModel.DataTransfer;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace TreeViewTest
{
    public sealed partial class MainPage : Page
    {
        private TreeViewNode deletedItem;
        private TreeView sourceTreeView;

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

        private void InitializeTreeView()
        {
            TreeViewNode parentNode1 = new TreeViewNode() { Content = "tv1" };
            TreeViewNode parentNode2 = new TreeViewNode() { Content = "tv2" };

            parentNode1.Children.Add(new TreeViewNode() { Content = "tv1FirstChild" });
            parentNode1.Children.Add(new TreeViewNode() { Content = "tv1SecondChild" });
            parentNode1.Children.Add(new TreeViewNode() { Content = "tv1ThirdChild" });
            parentNode1.Children.Add(new TreeViewNode() { Content = "tv1FourthChild" });
            parentNode1.IsExpanded = true;
            treeView1.RootNodes.Add(parentNode1);

            parentNode2.Children.Add(new TreeViewNode() { Content = "tv2FirstChild" });
            parentNode2.Children.Add(new TreeViewNode() { Content = "tv2SecondChild" });
            parentNode2.IsExpanded = true;
            treeView2.RootNodes.Add(parentNode2);
        }

        private void TreeView_DragOver(object sender, DragEventArgs e)
        {
            if (e.DataView.Contains(StandardDataFormats.Text))
            {
                e.AcceptedOperation = DataPackageOperation.Move;
            }
        }

        private async void TreeView_Drop(object sender, DragEventArgs e)
        {
            if (e.DataView.Contains(StandardDataFormats.Text))
            {
                string text = await e.DataView.GetTextAsync();
                TreeView destinationTreeView = sender as TreeView;

                if (destinationTreeView.RootNodes != null)
                {
                    TreeViewNode newNode = new TreeViewNode() { Content = text };
                    destinationTreeView.RootNodes[0].Children.Add(newNode);
                    deletedItem = newNode;
                }
            }
        }

        private void TreeView_DragItemsStarting(TreeView sender, TreeViewDragItemsStartingEventArgs args)
        {
            if (args.Items.Count == 1)
            {
                args.Data.RequestedOperation = DataPackageOperation.Move;
                sourceTreeView = sender;

                foreach (var item in args.Items)
                {
                    args.Data.SetText(item.ToString());
                }
            }
        }

        private void TreeView_DragItemsCompleted(TreeView sender, TreeViewDragItemsCompletedEventArgs args)
        {
            var children = sourceTreeView.RootNodes[0].Children;

            if (deletedItem != null)
            {
                for (int i = 0; i < children.Count; i++)
                {
                    if (children[i].Content.ToString() == deletedItem.Content.ToString())
                    {
                        children.RemoveAt(i);
                        break;
                    }
                }
            }

            sourceTreeView = null;
            deletedItem = null;
        }
    }
}