C# 自定义组合框 - 下拉位置

C# Custom ComboBox - DropDown Position

我正在使用 ToolStripControlHostToolStripDropDown 创建一个 ComboBox 控件,它可以在 DropDown window 中承载任何类型的控件。例如,DropDown window 可能会显示列表视图或树视图甚至另一个用户控件。

我在下面发布了一个简化的代码,其中下拉菜单包含一个带有列表视图和按钮的用户控件,如下所示:

当控件位于屏幕底部时,下拉菜单 window 将外推屏幕的下边界,就会出现问题。发生这种情况时,下拉菜单最终会隐藏控件。

在这种情况下,我想修复 _dropDown.Show 方法调用以显示下拉列表 window,如下所示:

要重复这个问题,只需 运行 下面的代码并将 window 拖到屏幕底部并打开下拉菜单。

using System;
using System.Windows.Forms;

public class CustomComboBox : UserControl
{
    ToolStripDropDown _dropDown;

    public CustomComboBox()
    {
        var textbox = new TextBox();
        textbox.Location = new System.Drawing.Point(0, 0);
        textbox.Size = new System.Drawing.Size(this.Width - 22, 20);
        textbox.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
        this.Controls.Add(textbox);

        var button = new Button();
        button.Location = new System.Drawing.Point(this.Width - 22, -1);
        button.Size = new System.Drawing.Size(22, 22);
        button.Text = "\u2BC6"; 
        button.Anchor = AnchorStyles.Right | AnchorStyles.Top;
        button.Click += new System.EventHandler(this.Button_Click);
        this.Controls.Add(button);

        var dropDownControl = new DropDownControlTest();

        var controlHost = new ToolStripControlHost(dropDownControl);

        _dropDown = new ToolStripDropDown();
        _dropDown.AutoSize = true;              
        _dropDown.Items.Add(controlHost); 
    }

    void Button_Click(object sender, EventArgs e)
    {
        _dropDown.Show(this, 0, this.Height);
    }
}

public class DropDownControlTest : UserControl
{
    public DropDownControlTest()
    {
        var listview = new ListView();
        listview.Location = new System.Drawing.Point(3, 1);
        listview.Size =  new System.Drawing.Size(400,300);
        listview.View = View.Details;
        listview.Columns.Add("Col 1",100);
        listview.Columns.Add("Col 2",100);
        this.Controls.Add(listview);

        var button = new Button();
        button.Location = new System.Drawing.Point(3, 305);
        button.Text = "More...";
        this.Controls.Add(button);
    }
}

public class Form1 : Form
{
    private static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    public Form1 ()
    {
        CustomComboBox ccBox = new CustomComboBox();
        ccBox.Location =  new System.Drawing.Point(10, 10);
        ccBox.Height = 20;

        this.Text = "Test CustomComboBox";
        this.Controls.Add(ccBox);
    }
}

我无法发表评论,所以我才回答你的问题。您可以使用反射,然后重新定位您的控件。我发现了一个与您开发的相同的自定义组合框控件。请检查 。至少,你会知道你需要做什么。

您可以使用 ToolStripDropDown.Show Method (Control, Point, ToolStripDropDownDirection) 重载来控制放置方向。该代码将需要执行边界检查来决定是将下拉列表放在文本框上方还是下方。

以下是进行边界检查的简单方法,仅在单个屏幕配置上进行了测试。

首先,使textbox成为class级变量。

private TextBox textbox;
public CustomComboBox()
    {
    //var textbox = new TextBox();
    textbox = new TextBox();

显示逻辑如下

void Button_Click(object sender, EventArgs e)
    {
    Point textBoxScreenLocation = textbox.PointToScreen(textbox.Location);

    // try to position _dropDown below textbox
    Point pt = textBoxScreenLocation;
    pt.Offset(0, textbox.Height);

    // determine if it will fit on the screen below the textbox
    Size dropdownSize = _dropDown.GetPreferredSize(Size.Empty);
    Rectangle dropdownBounds = new Rectangle(pt, dropdownSize);

    if (dropdownBounds.Bottom <= Screen.GetWorkingArea(dropdownBounds).Bottom)
        {   // show below
            _dropDown.Show(pt, ToolStripDropDownDirection.BelowRight);
        }
    else
        {   // show above
            _dropDown.Show(textBoxScreenLocation, ToolStripDropDownDirection.AboveRight);
        }
    }
}