2016-09-22 81 views
0

我有一個窗體包含一個TableLayoutPanel與其中的各種控件和標籤。其中一個是從ComboBox繼承的自定義控件,它具有額外的自動完成行爲(自動完成任何文本而不是從左到右)。我沒有爲這個控件編寫代碼,所以我對它的工作原理並不十分熟悉,但基本上在單擊Combobox時,它在ComboBox下面的TableLayoutPanel的同一個面板中添加了一個ListBox,它覆蓋正常下降。允許列表框重疊TableLayoutPanel(C#.NET)

不幸的是,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

+0

沒有孩子可以重疊它的容器。你可能想要[看看這篇文章](http://stackoverflow.com/questions/39637490/winforms-splitterpanel-z-index-of-child-overlap-split/39649087#39649087)。或者使用組合框;下拉菜單並不是真正的子控件,但顯示爲覆蓋,因此它們甚至可以重疊表單邊框。 – TaW

+0

我無法使用ComboBox,因爲它沒有我需要的額外自動完成功能。有趣的是,你所說的有關兒童控制的問題不能與他們的容器重疊。有道理,但我不知道在所有情況下都是如此。如果下拉菜單可以重疊一個容器,那麼不應該有某種方式來模仿自定義控件中的行爲嗎? – user2961731

+0

將Dropdowns視爲臨時窗口/表單!是的,這也是一個選擇..也許你可以編寫一個自動完成版本的combox,如果你找不到一個。 – TaW

回答

0

去從TAW的建議,我想出了一個試探性的解決方案。這種形式不是可以調整大小的,但會自動調整大小,以便用戶在Windows中更改其DPI時看起來不錯。

爲了解決這個問題,我將控件從TableLayoutPanel移出到TableLayoutPanel的Parent的任意位置。在表單加載中,我總結了TableLayoutPanel的座標和我希望控件位於頂部的單元格中的空面板。這工作適合我的需求,但它感覺像一個kludge。

更好的解決方案可能是使用Control.PointToScreen和Control.PointToClient方法,但是我無法讓這些方法給我正確的座標。