允许 ListBox 与 TableLayoutPanel 重叠 (C# .NET)

Allow a ListBox to overlap a TableLayoutPanel (C# .NET)

我有一个表单,其中包含一个带有各种控件和标签的 TableLayoutPanel。其中之一是继承自 ComboBox 的自定义控件,它具有额外的自动完成行为(自动完成任何文本,而不仅仅是从左到右)。我没有为这个控件编写代码,所以我不是很熟悉它是如何工作的,但基本上在单击 Combobox 时,它会在 ComboBox 下面添加一个 ListBox,在 TableLayoutPanel 的同一个面板中,它覆盖了正常下拉。

不幸的是,TableLayoutPanel 阻止了 ListBox 在添加时完全可见,并且只显示了一项。目标是让它看起来像一个普通的组合框,它会下拉以覆盖它下面的任何控件。

有没有什么方法可以让 TableLayoutPanel 中的控件与 TableLayoutPanel 重叠,使其按我的意愿工作?我想避免任何控件因 TableLayoutPanel 增长以容纳 ListBox 而四处移动。

控件相关代码:

void InitListControl()
        {
            if (listBoxChild == null)
            {
                // Find parent - or keep going up until you find the parent form
                ComboParentForm = this.Parent;

                if (ComboParentForm != null)
                {
                    // Setup a messaage filter so we can listen to the keyboard
                    if (!MsgFilterActive)
                    {
                        Application.AddMessageFilter(this);
                        MsgFilterActive = true;
                    }

                    listBoxChild = listBoxChild = new ListBox();
                    listBoxChild.Visible = false;
                    listBoxChild.Click += listBox1_Click;
                    ComboParentForm.Controls.Add(listBoxChild);
                    ComboParentForm.Controls.SetChildIndex(listBoxChild, 0); // Put it at the front
                }
            }
        }


        void ComboListMatcher_TextChanged(object sender, EventArgs e)
        {
            if (IgnoreTextChange > 0)
            {
                IgnoreTextChange = 0;
                return;
            }

            InitListControl();

            if (listBoxChild == null)
                return;

            string SearchText = this.Text;

            listBoxChild.Items.Clear();

            // Don't show the list when nothing has been typed
            if (!string.IsNullOrEmpty(SearchText))
            {
                foreach (string Item in this.Items)
                {
                    if (Item != null && Item.ToLower().Contains(SearchText.ToLower()))
                    {
                        listBoxChild.Items.Add(Item);
                        listBoxChild.SelectedIndex = 0;
                    }
                }
            }

            if (listBoxChild.Items.Count > 0)
            {
                Point PutItHere = new Point(this.Left, this.Bottom);
                Control TheControlToMove = this;

                PutItHere = this.Parent.PointToScreen(PutItHere);

                TheControlToMove = listBoxChild;
                PutItHere = ComboParentForm.PointToClient(PutItHere);

                TheControlToMove.Anchor = ((System.Windows.Forms.AnchorStyles)
                    ((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
                TheControlToMove.BringToFront();
                TheControlToMove.Show();
                TheControlToMove.Left = PutItHere.X;
                TheControlToMove.Top = PutItHere.Y;
                TheControlToMove.Width = this.Width;

                int TotalItemHeight = listBoxChild.ItemHeight * (listBoxChild.Items.Count + 1);
                TheControlToMove.Height = Math.Min(ComboParentForm.ClientSize.Height - TheControlToMove.Top, TotalItemHeight);
            }
            else
                HideTheList();
        }

图片:

Desired behavior

Current behavior

根据TaW的建议,我想出了一个初步的解决方案。此表单不可重新调整大小,但会自动调整大小,因此如果用户在 Windows.

中更改其 DPI,它看起来没问题

为了解决这个问题,我将控件从 TableLayoutPanel 移到了 TableLayoutPanel 的父级中的任意位置。在加载表单时,我将 TableLayoutPanel 的坐标和我希望控件位于其上的单元格中的空面板相加。这可以满足我的需要,但感觉就像是一种拼凑。

更好的解决方案可能是使用 Control.PointToScreen 和 Control.PointToClient 方法,但是我无法通过这些方法获得正确的坐标。