0

ツール ストリップ メニュー項目がいつ表示されるかを知る必要があります (JIT ベースでコンテンツを作成するため)。

私は潜在的に非常に大きなものの階層を持っています。ツリービューでナビゲートできますが、「ブレッドクラム」を介してナビゲートすることもできます。たとえば、「ミュージック > ポップ > マイケル ジャクソン > バッド」などです。ブレッドクラムはツールストリップによって実装され、各レベルには LinkLabel が表示されます。「音楽」などのリンクをクリックすると、現在の項目のすべての兄弟を含むコンテキスト メニューが動的に作成されます。

階層全体が常に読み込まれているような錯覚を起こそうとしています。データをフェッチするときは、ノードを提示するのに十分な情報を取得し、そのノードに子があるかどうかを確認します。子がある場合は、「このアイテムには子がアンロードされています」という特別な意味を持つダミー ノードを作成し、それを唯一の子として配置します。これにより、ツリービューはノードを展開可能としてレンダリングします。次に、ツリービューの BeforeExpand イベントを使用して次のレベルを取得し、実際に表示されるタイミングでノード コレクションを更新します。

これはツリーではうまく機能しますが、ブレッドクラム スタイルのコンテキスト メニューでも同じことを行う必要があります。子を持つアイテムのサブメニューを既に作成し、そこに特別な「アンロードされた子」アイテムを配置しています。問題は、サブメニューがいつ表示されるかを知らせるイベントが見つからないことです。これは、ホバリング、クリック、キーボード ナビゲーションなどによって発生する可能性があります。私が見つけていないより適切なフックがある場合、私は本当にそれをハックしたくありません..

言い換えれば、私が必要とするのは「BeforeExpand」に相当するものですが、ToolStripMenuItem の場合 (MS 独自の命名ガイドラインに従って、イベントは「NodeExpanding」と呼ばれるべきであり、動名詞形式 (「ing」) を使用する必要があります。 「Before」接頭辞ではなく過去時制 (「After」接頭辞ではなく「Expanded」)。

私がやろうとしていることは明らかであり、誰かがこれを解決する方法を知っていることを願っています!

4

1 に答える 1

0

Paintイベントを使用できることがわかりました。私はそれがうまくいくとは本当に思っていませんでしたが、うまくいきました。

ToolStripMenuItemに「item」という用語を使用し、階層内の論理ノードに「node」という用語を使用すると、Paintハンドラーを次のように疑似コード化できます(実際にはPoCプロジェクトのC#コード)。

void menuItem_Paint(object sender, PaintEventArgs e)
{
    var item = (ToolStripMenuItem)sender;

    var node = item.Tag as Node;
    if (node == null || node.Parent == null || node.Parent.RealChildren)
        return;

    node = node.Parent;
    item = FindMenuItem(menu.Items, node);

    if (node != null)
        ReplaceDummyWithData(node, item);
}

void ReplaceDummyWithData(Node node, ToolStripMenuItem item)
{
    Dbug("Removing dummy: {0}", node.Label);

    // Modify logical tree..
    node.Remove(node.Children[0]);
    MakeNode(node, "Data #1");
    MakeNode(node, "Data #2");

    // Rebuild menu items..
    item.DropDownItems.Clear();
    AddMenuItems(item.DropDownItems, node.Children);
    node.RealChildren = true;
}

私はこれがうまくいくとは本当に思っていませんでしたが、うまくいくようです。すべてのアイテムに「データ#1」と「データ#2」というラベルの付いた2つの子がある、無限に深い階層をハードコーディングしましたが、これを変更するのは難しくないため、アイテムは実際のデータに基づいて作成されます。重要なのは、メニュー項目のツリーをジャストインタイムで変更する方法を見つけることでした。これは、そのための許容可能な手段のようです。

FindMenuItemは、指定されたノードでタグ付けされたアイテムの再帰検索です。

ToolStripMenuItem FindMenuItem(ToolStripItemCollection collection, Node node)
{
    foreach (ToolStripMenuItem item in collection)
    {
        if (item.Tag == node)
            return item;

        var found = FindMenuItem(item.DropDownItems, node);
        if (found != null) 
            return found;
    }
    return null;
}

PoCのMakeNodeは常にダミーの子を作成しますが、データ駆動型の場合は、実際に子があるかどうかに基づいて作成します。

Node MakeNode(Node parent, string label)
{
    var n = new Node(parent) { Label = label, RealChildren = false };
    new Node(n) { Label = "dummy" };
    return n;
}

Nodeコンストラクターは親ノードを取ります。おそらく最も読みやすいコードではありません。これは私のPoCによるものであり、コードの目的は、他の点で優れたコードを作成することではなく、私の問題の解決策を見つけることでした。

于 2013-01-09T15:54:12.140 に答える