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

时间:2016-09-22 23:40:10

标签: c# .net tablelayoutpanel

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

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

有没有办法允许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

1 个答案:

答案 0 :(得分:0)

根据TaW的建议,我想出了一个初步的解决方案。此表单不具有可调整大小,但会自动调整大小,以便用户在Windows中更改其DPI时看起来没问题。

要解决此问题,我将控件从TableLayoutPanel移出到TableLayoutPanel的Parent中的任意位置。在表单加载时,我总结了TableLayoutPanel的坐标和单元格中的空面板,我想让控件位于顶部。这符合我的需求,但感觉就像一个kludge。

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