C# WPFのTreeViewで指定項目まで展開してスクロールする

ツリー構造を展開したり折りたたんだりして表示できるTreeViewコントロール。

TreeViewコントロールをマウスクリックで展開させるだけでなく、ある特定の項目まで展開しスクロールして表示させたいケースがあります。

 

ListViewクラスでは ScrollIntoView というメソッドがあり見える位置まてスクロールして表示してくれる機能がありますが、同様のことを TreeView でも行うにはどのようにすればよいでしょう?

 

参考:C# WPFのListViewで選択行を見える位置までスクロールする

 

TreeViewの使い方のおさらい

ここではTreeViewに対してデータをバインディングして使うことを想定しています。

TreeViewへデータをバインドする方法については以下を参照してください。

参考:C#のWPFでTreeViewへデータをバインドする

ItemContainerGeneratorとBringIntoView

TreeViewクラスには ItemContainerGenerator というプロパティがあります。

これをうまく使うことで、ツリーの各項目のUIコントロール(TreeViewItemクラス)を取得することが出来ます。

また、TreeViewItemクラスにはBringIntoViewというメソッドがあり、これを使えばこの項目が表示されるようスクロールしてくれます。

 

 

つまり、ItemContainerGenerator で該当のTreeViewItemを見つけ出し、そのTreeViewItemでBringIntoViewメソッドを呼び出せばよいのですが、TreeViewItemの探し方には工夫が必要です。

 

ItemContainerGenerator は子階層のUIコントロールを制御するもので、孫階層やさらに下の階層のことまで制御してくれません。下の階層まで探すためのコードを書く必要があります。

        private void BringIntoTreeView(TreeView view, TreeSource selectedSrc)
        {
            var queue = new System.Collections.Generic.Stack<TreeSource>();
            var src = selectedSrc;
            while (null != src)
            {
                queue.Push(src);
                src = src.Parent;
            }

            var generator = view.ItemContainerGenerator;
            while (0 < queue.Count)
            {
                src = queue.Pop();
                var treeViewItem = (TreeViewItem)generator.ContainerFromItem(src);
                if (null != treeViewItem)
                {
                    if (selectedSrc != src)
                    {
                        treeViewItem.IsExpanded = true;
                    }
                    else
                    {
                        treeViewItem.IsSelected = true;
                        treeViewItem.BringIntoView();
                    }
                    generator = treeViewItem.ItemContainerGenerator;
                }
            }
        }

データ階層を収集(3~9行目)

指定の項目から順に親要素を収集していきます。

 

親要素から順にTreeViewItemを取得(11~29行目)

最初はTreeViewからItemContainerGeneratorを取得します。

ContainerFromItemメソッドを使うと指定したデータに対応するTreeViewItemを取得できます。

親階層の項目であれば、IsExpandedプロパティを true にしてツリーを展開表示し、さらに下層のコントロールを探すため、TreeViewItemからItemContainerGeneratorを取り直します。

目的の項目であれば、BringIntoViewメソッドを呼び出してスクロールさせます。