政彦2005/02/04「TIPS:TreeViewコントロールへ項目を追加するには?」では、TreeViewコントロールでツリーを構築するために、複数のツリーのデータ項目(ノード)をまとめて登録する方法や1つずつ追加する方法を紹介した。複数のノードをまとめて追加するツリー構築手法は、そのツリー形状が固定的な場合には最も効率がよい。レジストリ・エディタやエクスプローラのように、ツリー階層が非常に深く、またその深さが不定の場合、ツリー全体の項目を最初にすべて追加しようとすると、その処理に時間がかかってしまい、アプリケーションのパフォーマンスが低下する可能性がある。そこで、本稿では適切なタイミングで必要なだけのツリー・ノードを追加する方法を紹介する。これにより、ツリー全体の構築が効率的になる。適切なタイミングで必要なだけのツリー・ノードを追加する方法TreeViewコントロールに最も効率的にノードを登録できるタイミングは、TreeViewコントロールのBeforeExpandイベントが発行されたときである。このBeforeExpandイベントは、ノードが展開される直前に発行される。このイベントのタイミングで展開されようとしているノードに子ノードを追加すればよいのだが、それだけではそれぞれの子ノードが展開可能かどうか(子ノードを持っているかどうか)を示すことができない(ノードに子ノードがあり展開可能な場合には、それを示す「+」マークがノードの左横に表示される。TreeViewコントロールのShowPlusMinusプロパティがTrueの場合のみ。このため、あるノードが展開されるときには、それより2段階下のノード(以降、孫ノード)まで追加しておかなければないということになる。言葉の説明だけではなかなかイメージしづらいので、具体的な例を使って説明することにしよう。ここでは、ツリー全体が次のような構造であるとする。上記のツリーの「食べ物」のノードを展開しようとしている場合、「果物」と「野菜」の子ノードを追加しているだけでは、「果物」の左横に展開可能な「+」マークが表示されない。このため「食べ物」のノードが展開される直前には、「果物」に対して「りんご」と「みかん」(「食べ物」から見ると、孫ノード)が追加されていなければならないのである。BeforeExpandイベントはノードが展開されるたびに発行されるので、同じノードが何度も登録されないようにするために、何らかの手段で子ノードがすでに追加済みかどうかを管理する必要がある。●子ノードの管理機能を持つ独自のTreeNodeExクラスそこで本稿では、ノードを表すTreeNodeクラス(System.Windows.Forms名前空間)を継承して、そのような管理機能をノード自身に持たせることにする。このようにして作成したTreeNodeExクラスを以下に示す。Class子ノードが追加済みかどうかを管理する機能を持つTreeNodeExクラス(VB.NET)上記のTreeNodeExオブジェクトを、ツリーに追加するノード・オブジェクトとして、TreeNodeオブジェクトの代わりに使えばよい。効率的にツリーが構築されるサンプル・プログラムそれでは、実際にBeforeExpandイベントでノードを追加するプログラムを作成してみよう。このサンプル・プログラムは、レジストリ・キーのツリー構造を表示するプログラムだ。以下の画面は、そのサンプル・プログラムを実行しているところである。上のサンプル・プログラムのTreeViewコントロールのツリー・ノードを実際に追加している部分のコードを以下に抜粋して示す。TreeViewコントロールのデータを更新します。ノードからパスを取得します。ノードからパスを取得します。.NETプロジェクト(createtreeview_vb.zip)のダウンロードまず初期表示として(フォームのLoadイベント・ハンドラで)、RefreshTreeViewメソッドによりあらかじめ基本となるノードを追加する。BeforeExpandイベントのイベント・ハンドラであるtreeView1_BeforeExpandメソッドで順次、必要なだけのノードを追加していく、という内容のコードになっている。RefreshTreeViewメソッドでは、TreeViewコントロールのNodesプロパティのAddメソッドにより、ツリーにノードを追加している。注意点としては、本稿では、追加するすべてのノードを前述のTreeNodeExオブジェクトにしているということだ。このNodesプロパティのAddメソッドは、実際にはノードのコレクションを示すTreeNodeCollectionクラス(System.Windows.Forms名前空間)のメソッドである。詳しくは前掲のTIPSを参照してほしい。treeView1_BeforeExpandメソッドでは、そのパラメータに引き渡されるTreeViewCancelEventArgsオブジェクト(System.Windows.Forms名前空間)のNodeプロパティ(=「展開されようとしているノード」)のNodesプロパティからすべての「子ノード」を取得し、それぞれの子ノードが所有するサブ・キーを取得して、子ノードのNodesプロパティ(これも実体はTreeNodeCollectionオブジェクト)のAddメソッドにより、そのサブ・キーを子ノードの下に(「孫ノード」として)追加している。そのサブ・キーの取得では、RegistryUtilityクラスのGetSubKeysメソッドを利用している。RegistryUtilityクラスはレジストリからキー情報を得るために自作した本稿独自のクラスで、そのGetSubKeysメソッドはパラメータに指定したレジストリ・キー・パスの配下にあるすべてのサブ・キー名を文字列配列として返すメソッドである。レジストリ・キー・パスはGetPathFromNodeメソッドにより取得している。GetPathFromNodeメソッドは、パラメータに指定されたノードのパスを文字列として返すメソッドである。コンピュータ」というノードが展開される。この場合にもBeforeExpandイベントが発行されるので、初期の状態ですでに「マイコンピュータ」の子ノード(例えば、「HKEY_LOCAL_MACHINE」)に、そのサブ・キーのノード(「マイコンピュータ」から見ると、孫ノード)が追加されることになる。後はクリックなどによりノードを展開するたびに、そこで必要となるノードが追加され、ツリー全体が徐々に構築されることになる。より自動抽出したものです。7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。TranslatorはPowerPoint用のアドイン。