かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

WPF4.5入門 その25 「TreeViewコントロール その1」

1月ほど間があきましたが、RIAアーキテクチャ研究会やめとべやでの発表も終わりひと段落ついたので、ちまちま再開していきたいなと思います。過去記事一覧が長くなってきたので、今回からは末尾にもってくようにしました。


TreeViewコントロール

TreeViewコントロールは、Windowsのエクスプローラーの左側のような入れ子構造のデータを表示するのに適したコントロールです。TreeViewコントロールの見た目を以下に示します。

TreeViewコントロールは、ItemsプロパティにTreeViewItemコントロールを設定することで木構造のデータを表現します。TreeViewItemコントロールは、Headerプロパティでツリーに表示する要素を指定して、ItemsプロパティでTreeViewItemコントロールを子として格納します。TreeViewコントロールもTreeViewItemコントロールもItemsプロパティがコンテンツプロパティなので、シンプルに木構造をXAMLで定義できます。以下に、上図のTreeViewコントロールのXAMLの定義を示します。

<TreeView>
    <TreeViewItem Header="Item1">
        <TreeViewItem Header="Item1-1">
            <TreeViewItem Header="Item1-1-1" />
            <TreeViewItem Header="Item1-1-2" />
            <TreeViewItem Header="Item1-1-3" />
        </TreeViewItem>
        <TreeViewItem Header="Item1-2">
            <TreeViewItem Header="Item1-2-1" />
            <TreeViewItem Header="Item1-2-2" />
        </TreeViewItem>
    </TreeViewItem>
    <TreeViewItem Header="Item2" IsExpanded="True">
        <TreeViewItem Header="Item2-1" IsExpanded="True" IsSelected="True">
            <TreeViewItem Header="Item2-1-1" />
            <TreeViewItem Header="Item2-1-2" />
            <TreeViewItem Header="Item2-1-3" />
        </TreeViewItem>
    </TreeViewItem>
</TreeView>

上記XAMLにあるように、IsExpandedプロパティでツリーが展開されているかどうか。IsSelectedプロパティで選択中のノードを指定します。
ここまでに出てきたTreeViewコントロールのプロパティを以下に示します。

プロパティ名 説明
ItemCollection Items { get; } TreeViewコントロールに表示する要素を格納するコレクションを取得します。

ここまでに出てきたTreeViewItemコントロールのプロパティを以下に示します。

プロパティ名 説明
object Header { get; sest; } ツリーに表示する要素を取得または設定します。コンテンツモデルで紹介した表示ロジックによって要素が表示されます。
ItemsCollection Items { get; } TreeViewItemコントロールの子要素を格納するコレクションを取得します。
bool IsExpanded { get; set; } 要素が展開されているかどうかを取得または設定します。
bool IsSelected { get; set; } 要素が選択されているかどうかを取得または設定します。

これらのプロパティを組み合わせて使うことで、静的なツリー場合は簡単にWindows Formsでは表現が難しかった表現も簡単に表示することが出来ます。XAMLを以下に示します。

<TreeView>
    <TreeViewItem IsExpanded="True">
        <TreeViewItem.Header>
            <StackPanel Orientation="Horizontal">
                <Rectangle Fill="Olive" Width="15" Height="15" />
                <TextBlock Text="矢印アイコン" Margin="5,0" />
                <Rectangle Fill="Olive" Width="15" Height="15" />
            </StackPanel>
        </TreeViewItem.Header>
        <TreeViewItem>
            <TreeViewItem.Header>
                <StackPanel Orientation="Horizontal">
                    <Grid Margin="2.5">
                        <Ellipse Width="20" Height="20" Stroke="Olive" StrokeThickness="2" />
                        <TextBlock Text="↑" HorizontalAlignment="Center" 
VerticalAlignment="Center" FontWeight="Bold" Foreground="Olive" />
                    </Grid>
                    <TextBlock Text="上矢印" VerticalAlignment="Center" />
                </StackPanel>
            </TreeViewItem.Header>
        </TreeViewItem>
        <TreeViewItem>
            <TreeViewItem.Header>
                <StackPanel Orientation="Horizontal">
                    <Grid Margin="2.5">
                        <Ellipse Width="20" Height="20" Stroke="Olive" StrokeThickness="2" />
                        <TextBlock Text="→" HorizontalAlignment="Center" 
VerticalAlignment="Center" FontWeight="Bold" Foreground="Olive" />
                    </Grid>
                    <TextBlock Text="右矢印" VerticalAlignment="Center" />
                </StackPanel>
            </TreeViewItem.Header>
        </TreeViewItem>
        …省略…
    </TreeViewItem>
</TreeView>

TreeViewItemコントロールのHeaderプロパティに、StackPanelコントロールやGridコントロールを使って複数のコントロールをレイアウトしています。RectangleやEllipseは、まだ紹介していませんがWPFで基本的な図形を表す要素です。実行結果を以下に示します。

WPFの強力な機能の1つである要素の合成と、TreeViewコントロールを使うことで、オーナードローなどの特別な記述を行わなくても、凝った表示ができることがわかります。