|
.NET TIPS TreeViewコントロールで効率的にツリーを構築するには?デジタルアドバンテージ 一色 政彦2005/02/04 |
![]() |
|
|
|
「TIPS:TreeViewコントロールへ項目を追加するには?」では、TreeViewコントロールでツリーを構築するために、複数のツリーのデータ項目(ノード)をまとめて登録する方法や1つずつ追加する方法を紹介した。
特に複数のノードをまとめて追加するツリー構築手法は、そのツリー形状が固定的な場合には最も効率がよい。しかし例えばレジストリ・エディタやエクスプローラのように、ツリー階層が非常に深く、またその深さが不定の場合、ツリー全体の項目を最初にすべて追加しようとすると、その処理に時間がかかってしまい、アプリケーションのパフォーマンスが低下する可能性がある。
そこで、本稿では適切なタイミングで必要なだけのツリー・ノードを追加する方法を紹介する。これにより、ツリー全体の構築が効率的になる。
適切なタイミングで必要なだけのツリー・ノードを追加する方法
TreeViewコントロールに最も効率的にノードを登録できるタイミングは、TreeViewコントロールのBeforeExpandイベントが発行されたときである。このBeforeExpandイベントは、ノードが展開される直前に発行される。
このイベントのタイミングで展開されようとしているノードに子ノードを追加すればよいのだが、それだけではそれぞれの子ノードが展開可能かどうか(子ノードを持っているかどうか)を示すことができない(ノードに子ノードがあり展開可能な場合には、それを示す「+」マークがノードの左横に表示される。ただし、TreeViewコントロールのShowPlusMinusプロパティがTrueの場合のみ。既定ではTrue)。このため、あるノードが展開されるときには、それより2段階下のノード(以降、孫ノード)まで追加しておかなければないということになる。
言葉の説明だけではなかなかイメージしづらいので、具体的な例を使って説明することにしよう。
ここでは、ツリー全体が次のような構造であるとする。

例えば上記のツリーの「食べ物」のノードを展開しようとしている場合、「果物」と「野菜」の子ノードを追加しているだけでは、「果物」の左横に展開可能な「+」マークが表示されない。このため「食べ物」のノードが展開される直前には、「果物」に対して「りんご」と「みかん」(「食べ物」から見ると、孫ノード)が追加されていなければならないのである。
ただし、BeforeExpandイベントはノードが展開されるたびに発行されるので、同じノードが何度も登録されないようにするために、何らかの手段で子ノードがすでに追加済みかどうかを管理する必要がある。
●子ノードの管理機能を持つ独自のTreeNodeExクラス
そこで本稿では、ノードを表すTreeNodeクラス(System.Windows.Forms名前空間)を継承して、そのような管理機能をノード自身に持たせることにする。このようにして作成したTreeNodeExクラスを以下に示す。
|
|
| 子ノードが追加済みかどうかを管理する機能を持つTreeNodeExクラス(C#) |
|
|
| 子ノードが追加済みかどうかを管理する機能を持つTreeNodeExクラス(VB.NET) |
上記のTreeNodeExオブジェクトを、ツリーに追加するノード・オブジェクトとして、TreeNodeオブジェクトの代わりに使えばよい。
効率的にツリーが構築されるサンプル・プログラム
それでは、実際にBeforeExpandイベントでノードを追加するプログラムを作成してみよう。このサンプル・プログラムは、レジストリ・キーのツリー構造を表示するプログラムだ。
以下の画面は、そのサンプル・プログラムを実行しているところである。
![]() |
| TreeViewコントロールのサンプル・プログラムの実行結果 |
●BeforeExpandイベント・ハンドラによる孫ノードの追加
上のサンプル・プログラムのTreeViewコントロールのツリー・ノードを実際に追加している部分のコードを以下に抜粋して示す。
|
|
| TreeViewコントロールにノードを効率的に追加するサンプル・コード(C#) | |
|
|
| TreeViewコントロールにノードを効率的に追加するサンプル・コード(VB.NET) | |
まず初期表示として(フォームの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メソッドは、パラメータに指定されたノードのパスを文字列として返すメソッドである。
なおコードの実行時には、RefreshTreeViewメソッドの最後にTreeViewコントロールのTopNodeプロパティのExpandメソッドを呼び出しているため、ツリーに最初に追加した「マイ コンピュータ」というノードが展開される。この場合にもBeforeExpandイベントが発行されるので、初期の状態ですでに「マイコンピュータ」の子ノード(例えば、「HKEY_LOCAL_MACHINE」)に、そのサブ・キーのノード(「マイコンピュータ」から見ると、孫ノード)が追加されることになる。
後はクリックなどによりノードを展開するたびに、そこで必要となるノードが追加され、ツリー全体が徐々に構築されることになる。![]()
| カテゴリ:Windowsフォーム 処理対象:TreeViewコントロール 使用ライブラリ:TreeNodeクラス(System.Windows.Forms名前空間) 使用ライブラリ:TreeNodeCollectionクラス(System.Windows.Forms名前空間) 使用ライブラリ:TreeViewCancelEventArgsクラス(System.Windows.Forms名前空間) 関連TIPS:TreeViewコントロールへ項目を追加するには? |
| 「.NET TIPS」 |
TechTargetジャパン
- Kinectが切り開く“夢の近未来” (2012/2/2)
日本を含めた世界中でKinect for Windowsセンサー商用版とSDK正式版がリリース。未来のコンピューティングはどう変化するのか? - 3つの視点でネイティブと.NETの適材適所を考察 (2012/1/31)
アプリ開発は「ネイティブ」と「.NET」、どちらが最良? その問いには「適材適所」と答えるしかない。では、“適所”は一体どこかを考察する - SQL Azure Data Sync入門 (2012/1/30)
SQL Azure/SQL Serverデータベース間のデータ同期を簡単に実現するサービスとは? その仕組みや使用手順を解説 - Windows Phoneアプリ市場の現状を分析する (2012/1/27)
Windows Phone のアプリ・ストアに日々登録されている多種多様なアプリ。カテゴリ別のアプリ数は? 市場の現状を明らかにする
|
|
キャリアアップ
スポンサーからのお知らせ
- - PR -
イベントカレンダー
- - PR -



