C#WPFの道#23!TreeViewの書き方と使い方を解りやすく解説

当サイトではアフィリエイト広告を利用しています。

WPF

TreeViewとは?

TreeViewとは,階層構造を表すことのできるコントロールです。ちょうどWindowsのファイルエクスプローラーのような感じです。フォルダーの下にフォルダーがあって,その下にファイルがあるみたいな感じで,階層構造になっていますよね。そういう親のしたに子がいて,さらにその子にも子階層があるというような構造をツリー構造(木構造)といい,それを見た目に表すことのできるコントロールという事になります。

TreeViewの書き方

TreeViewの書き方には,あらかじめ表示する内容が決まっている場合等に利用できる「静的」なやり方と,データバインドを使用した「動的」な設定の仕方があります。

静的な書き方

XamlでTreeViewの中にTreeViewItemを作ることで,一つの階層を作ることができます。そのTreeViewItemにもさらにTreeViewItemを作成することができ,その繰り返しにより,親子関係を定義します。階層に表示される文言はHeaderに設定します。

<TreeView FontSize="20">
    <TreeViewItem Header="A部">
        <TreeViewItem Header="Aグループ">
            <TreeViewItem Header="グループ員1"/>
            <TreeViewItem Header="グループ員2"/>
            <TreeViewItem Header="グループ員3"/>
        </TreeViewItem>
    </TreeViewItem>
</TreeView>
  • TreeViewItemの中にTreeViewItemを作ることで,親子階層になる
  • TreeViewItemのHeaderが階層のタイトルになる

実行例

TreeViewItem.Headerを利用することで,文言の部分をマーク付きの文言にするなどの加工が簡単に行えます。

<TreeView FontSize="20">
    <TreeViewItem>
        <TreeViewItem.Header>
            <StackPanel Orientation="Horizontal">
                <Ellipse Height="10"
                         Width="10"
                         Margin="6"
                         Fill="Red"/>
                <TextBlock Text="B部"/>
            </StackPanel>
        </TreeViewItem.Header>
        <TreeViewItem Header="グループ員1"/>
    </TreeViewItem>
</TreeView>
  • TreeViewItemに直接Headerを指定せず,Headerを定義
  • HeaderにStackPanelを定義し,任意のコントロールを配置
  • 赤い丸の右にテキストブロックで文言を表示

実行例

データバインディングを使った動的な設定例

///
/// MainWindow.xaml の相互作用ロジック
/// 
public partial class MainWindow : Window
{
    private ObservableCollection _dtos = new ObservableCollection();
    public MainWindow()
    {
        InitializeComponent();

        var dto1 = new Dto("Name1");
        dto1.Dtos.Add(new Dto("Name1-1"));
        dto1.Dtos.Add(new Dto("Name1-2"));
        _dtos.Add(dto1);

        CTreeView.ItemsSource = _dtos;
    }
}

public sealed class Dto
{
    public Dto(string name)
    {
        Name = name;
    }

    public string Name { get; set; }
    public List Dtos { get; set; } = new List();
}
  • まずデータバインディングを行うための型となるクラスを作成します。ここではDtoとしています。
  • Dtoは階層名を表示するためのNameプロパティと,自分自身の子階層を表すDtosのプロパティがあります。
  • Dtosのプロパティは,親階層と同じDtoクラスのListになっています。
  • PrivateフィールドにDtoのリストを生成しています(_dtos)。これがTreeViewのItemsSourceとなります。
  • dto1を生成しています。これは親階層のNameを「Name1」とし,その子階層を「Name1-1」「Name1-2」としています。
  • dto1を_dtosにAddし,それをCTreeViewのItemsSourceにセットしています。
<TreeView x:Name="CTreeView" FontSize="20">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate DataType="local:Dto"
                                  ItemsSource="{Binding Dtos}">
            <TextBlock Text="{Binding Name}"/>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>
  • TreeViewの名前をCTreeViewにしています。
  • ItemTemplateとHierarchicalDataTemplateのエリアを作成
  • HierarchicalDataTemplateのDataTypeに階層の型となるクラス名「Dto」を指定します
  • ItemsSourceにはDtoの子階層のプロパティ名を指定します「Dtos」
  • 階層名として表示するエリアをTextBlockで表示するためにNameをBindingします

実行結果

サンプルコード全体

<Window x:Class="WPF023.MainWindow"
        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:local="clr-namespace:WPF023"
        mc:Ignorable="d"
        Title="MainWindow" Height="300" Width="300">
    <Grid>
        <StackPanel>
            <TreeView FontSize="20">
                <TreeViewItem Header="A部">
                    <TreeViewItem Header="Aグループ">
                        <TreeViewItem Header="グループ員1"/>
                        <TreeViewItem Header="グループ員2"/>
                        <TreeViewItem Header="グループ員3"/>
                    </TreeViewItem>
                </TreeViewItem>
            </TreeView>

            <TreeView FontSize="20">
                <TreeViewItem>
                    <TreeViewItem.Header>
                        <StackPanel Orientation="Horizontal">
                            <Ellipse Height="10"
                                     Width="10"
                                     Margin="6"
                                     Fill="Red"/>
                            <TextBlock Text="B部"/>
                        </StackPanel>
                    </TreeViewItem.Header>
                    <TreeViewItem Header="グループ員1"/>
                </TreeViewItem>
            </TreeView>

            <TreeView x:Name="CTreeView" FontSize="20">
                <TreeView.ItemTemplate>
                    <HierarchicalDataTemplate DataType="local:Dto"
                                              ItemsSource="{Binding Dtos}">
                        <TextBlock Text="{Binding Name}"/>
                    </HierarchicalDataTemplate>
                </TreeView.ItemTemplate>
            </TreeView>
        </StackPanel>
    </Grid>
</Window>
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;

namespace WPF023
{
    ///
    /// MainWindow.xaml の相互作用ロジック
    /// 
    public partial class MainWindow : Window
    {
        private ObservableCollection _dtos = new ObservableCollection();
        public MainWindow()
        {
            InitializeComponent();

            var dto1 = new Dto("Name1");
            dto1.Dtos.Add(new Dto("Name1-1"));
            dto1.Dtos.Add(new Dto("Name1-2"));
            _dtos.Add(dto1);

            CTreeView.ItemsSource = _dtos;
        }
    }

    public sealed class Dto
    {
        public Dto(string name)
        {
            Name = name;
        }

        public string Name { get; set; }
        public List Dtos { get; set; } = new List();
    }
}