1

ドロップダウン部分にツリーが含まれる独自の ComboBox のようなコントロールを作成しました。通常の ComboBox を使用して WndProc を上書きするこれらのソリューションを見てきましたが、非常に多くのコードにもかかわらず、常に奇妙な動作がありました。そこで、単純にすることにしました。マウスがラベル上に置かれたときに開かれる ToolStripDropDown/ToolStripControlHost を持つラベルだけです。ComboBox の三角形が欠けていても問題ありません。

1 つの小さなことを除いて、すべてが完全に機能します。標準の ComboBox のように、ラベルをもう一度クリックするとドロップダウンが非表示になるようにします。しかし、それをクリックすると、ドロップダウンが一瞬非表示になり、再び表示されます。ラベルの外側をクリックすると、ドロップダウンが非表示になります。

public class RepoNodeComboBox: Label
{
    RepoTreeView repoTreeView;
    ToolStripControlHost treeViewHost;
    ToolStripDropDown dropDown;
    bool isDropDownOpen;

    public int DropDownHeight;

    public RepoNodeComboBox()
    {
        repoTreeView = new RepoTreeView();
        repoTreeView.BorderStyle = BorderStyle.None;
        repoTreeView.LabelEdit = false;

        treeViewHost = new ToolStripControlHost(repoTreeView);
        treeViewHost.Margin = Padding.Empty;
        treeViewHost.Padding = Padding.Empty;
        treeViewHost.AutoSize = false;

        dropDown = new ToolStripDropDown();
        dropDown.CanOverflow = true;
        dropDown.AutoClose = true;
        dropDown.DropShadowEnabled = true;
        dropDown.Items.Add(treeViewHost);
        dropDown.Closing += dropDownClosing;

        TextAlign = ContentAlignment.MiddleLeft;
        BackColor = SystemColors.Window;
        BorderStyle = BorderStyle.FixedSingle;

        DropDownHeight = 400;
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing) 
        {
            if (dropDown != null) 
            {
                dropDown.Dispose();
                dropDown = null;
            }
        }
        base.Dispose(disposing);
    }

    // when mouse goes down on the label, this is executed first            
    void dropDownClosing(object sender, System.ComponentModel.CancelEventArgs e)
    {
        // just to test if I can get more out of it than with dropdown.Visible
        isDropDownOpen = false; 
    }

    // this is subsidiary to the Closing event of the dropdown
    protected override void OnMouseDown(MouseEventArgs e)
    {
        if (dropDown != null) 
        {
            if (isDropDownOpen)
            {
                dropDown.Hide();
            }
            else
            {
                repoTreeView.Size = new Size(Width, DropDownHeight);
                treeViewHost.Width = Width;
                treeViewHost.Height = DropDownHeight;
                dropDown.Show(this, 0, Height);
                isDropDownOpen = true;
            }
        }

        base.OnMouseDown(e);
    }
}

私が見る限り(ブレークポイント)、ドロップダウンは最初に MOUSEDOWN イベントをキャッチして、それ自体を閉じます。その後、ラベルが MOUSEDOWN イベントを通過し、ドロップダウンが閉じられていることがわかるため、ラベルが初めてクリックされたと見なされ、ドロップダウンが再び開きます。

そのため、ラベルは MOUSEDOWN がドロップダウン項目を閉じた結果であるかどうかを知る機会がないようです。1 つおきのイベントで開くこともできますが、その場合、他の終了イベントが発生する必要はありません。

ラベルをクリックしても、開いているドロップダウン項目が確実に閉じるようにする方法はありますか?

4

1 に答える 1