11

C# で記述されたレガシー アプリケーションがあり、1 万から 2 万の要素を持つ非常に複雑なツリービューが表示されます。

過去に、Win32 API が提供する OWNERDATA 機能で解決した同様の問題 (ただし C++ で) に遭遇しました。

C#にも同様のメカニズムはありますか?

編集: 計画は、作成時間と閲覧時間を最適化することです。Win32 API を介して利用できる方法は、初期化時間をゼロに短縮し、要素に対する要求の数が一度に表示されるものだけに制限されるため、これらの両方の場合に優れています。Joshl: 私たちは実際にあなたが提案したことをすでに実行していますが、さらに効率化する必要があります。

4

7 に答える 7

21

パフォーマンスを改善する 1 つの手法は、ユーザーがツリービューを展開するときに TreeNode をロードすることです。通常、ユーザーは画面上で一度に 20,000 個のノードを開く必要はありません。ユーザーにアフォーダンスを適切に表示するために必要な子情報 (子が存在する場合は展開アイコン、カウント、アイコンなど) と共に、ユーザーが見る必要があるレベルのみを読み込みます。ユーザーがノードを展開すると、ちょうど間に合うように子をロードします。

キースからの役立つヒント: winforms TreeView では、少なくとも 1 つの子ノードが必要です。そうしないと、展開 [+] が表示されませんが、TreeNodeExpanded イベントを処理して、そのダミー ノードを削除し、子ノードを設定します。

于 2008-09-23T13:53:11.433 に答える
15

メインの WinForm アプリでは、ツリービューをすべて 1 回で読み込んでいます。

  • BeginUpdate()
  • 20.000 ノードをロード
  • EndUpdate()

これまでのところ、パフォーマンスはまだ素晴らしいです。これは、実際には、サードパーティのものと交換していない数少ないコンポーネントの 1 つです。

私の経験では、特にノードがソートされている場合、Begin/EndUpdate() を呼び出さずにノードをロードすると (ワンショットまたはオンデマンドで) TreeView のパフォーマンスが低下しますが、Begin/EndUpdate() を正しく呼び出すと、コンポーネント自体に関連するパフォーマンスの問題は実際には発生しないはずです。

于 2008-09-23T15:04:25.100 に答える
7

注:この回答は、質問者がこの種のことをすでに行っているという編集によって無効になっていますが、このトピックを検索している他の人が将来参照できるように投稿することにしました

過去に同様のことを行ったとき、単純な遅延読み込みスタイルを選択する傾向がありました。

  • プロパティを使用TreeNode.Tagして、子を検索するために使用できる参照を保持します
  • イベントを使用しTreeView.BeforeExpandて子ノードを設定します
  • 必要に応じて、イベントを使用しTreeView.AfterCollapseてそれらを削除します。
  • [+]/[-] ボックスを表示するには、私が見つけた最良の方法は、TreeNode未実装のすべてのノードに子として追加されるシングルトン ダミーを作成することですBeforeExpand
于 2008-09-23T14:27:59.367 に答える
7

このタイプのモデルは .NET の DataGridView (DataGridView のVirtualModeプロパティを参照) でサポートされていますが、.NET TreeView があなたが望むものをサポートしているとは思いません。TreeView を使用すると、独自のノードを描画できますが、仮想ストアからノードを作成することはできません。

可能であれば、アプリケーションに DataGridView を使用することを検討してください。そうでない場合は、ノードが展開されたときに画面を適切に更新することでいくつかの問題を回避できれば、(上記の joshl の言及のように) ノードを手動で管理するとうまくいく可能性があります。それ以外では、この (Divelements SandGrid)のように、目的の操作モードをサポートする可能性がある (可能性を強調する)サードパーティ ベンダーを確認することをお勧めします。

注: 2013 年 7 月末現在、SandGrid は Divelements によってサポートされていません。

于 2008-09-23T14:08:37.277 に答える
5

TreeView のパフォーマンスを大幅に向上させる方法が 1 つあります。それは、すべてのサブノードを作成し、それらをまとめてフックし、ノードを TreeView に追加することですそれが私たちが話しているグラフィックパフォーマンスである場合。

TreeView tree = new TreeView();
TreeNode root = new TreeNode("Root");
PopulateRootNode(root); // Get all your data
tree.Nodes.Add(root);

それ以外の場合は、 OnTreeNodeExpandedを使用してノードごとにロードします。

于 2008-09-23T14:18:26.490 に答える
1

Windows C# プログラミングの大きなデータの場合、それが WPF であろうと WinForms であろうと、私は伝統的にノードを動的に追加してきました。初期ツリーのルート + 子 + 孫を深くロードします。いずれかのノードが展開されると、展開するノードの孫を表すツリー ノードがあればそれを読み込みます。

このパターンは、データ検索でもうまく機能します。本当に数千または数百万のレコードのソースからデータをロードしている場合は、それらすべてを事前にロードしたくないでしょう。ユーザーはそれがロードされるのを待ちたくありませんし、表示されることのないデータをロードする理由はありません。

私は通常、バックグラウンド スレッドで必要に応じて孫ノードまたはひ孫ノード データをロードし、それらのデータを UI スレッドにマーシャリングし、ノードを作成して追加します。これにより、UI の応答性が維持されます。ツリー ノードを視覚的に装飾して、ユーザーがデータ ストアへの IO を先取りした場合に備えて、まだロード中であることを示すことができます。

于 2008-09-23T14:49:47.397 に答える
0

これは私にとってはうまくいきます(CSharp):

    Visible = false;
    ...
    Visible = true;

私の場合 (2000 ノード)、ツリーをロードするのに 1~2 秒しかかからず、他のどの方法よりもはるかに高速です。C++でうまくいくかもしれません。

于 2022-02-23T13:51:02.800 に答える