C#Custom ComboBox - DropDown Position

时间:2018-01-04 01:28:08

标签: c# winforms combobox user-controls dropdown

我正在使用ToolStripControlHostToolStripDropDown创建一个ComboBox控件,它可以在DropDown窗口中托管任何类型的控件。例如,DropDown窗口可能会显示listview或treeview,甚至是其他用户控件。

我在下面发布了一个简化的代码,其中dropdown托管一个带有listview的用户控件和一个这样的按钮:

enter image description here

当控件位于屏幕底部时,下拉窗口将推断屏幕的下边界,就会出现问题。发生这种情况时,下拉列表最终会隐藏控件。

在这种情况下,我想修改_dropDown.Show方法调用以显示下拉窗口,如下所示:

enter image description here

要重复此问题,只需运行下面的代码并将窗口拖到屏幕底部并打开下拉列表。

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);
    }
}

2 个答案:

答案 0 :(得分:4)

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

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

首先,使textbox成为一个类级变量。

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);
        }
    }
}

答案 1 :(得分:2)

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