2012-09-14 130 views
2

我試圖找出填充從選擇列表中的地址域(含糊,但閱讀)的最佳方式..多線組合框下拉列表

佈局:

enter image description here

當我選擇地址下拉菜單,我希望看到一個完整的地址列表,例如,街道名稱,國家,郵政編碼等,但我確定你知道,組合只有一行。

理想的方案:

enter image description here

結果:

enter image description here

有沒有人這樣做的方法?

+1

看看[此](http://stackoverflow.com/questions/4001450/allow-each-item-to-use-multiple-lines- in-a-winforms-combobox-or-listbox)SO主題 –

+0

有趣的..現在正在尋找與該答案一起工作。謝謝! – Christian

+0

@JordyvanEijk:終於有了完整的解決方案。需要創建一個自定義的ComboBox類,因爲如果第一個很小,dropdownheight會變得混亂。以下完整解決方案謝謝! – Christian

回答

5

下面是完整的解決方案,正如你所看到的,它的完美我想要的。

enter image description here

的ComboBoxEx是從我抄最後一個ComboBox派生的類。其原因是設置Items容器的高度(DropDownHeight)。沒有它,容器是根據第一個項目x no的大小計算的。的項目,並且由於第一項是零高度,容器將是零高度。所以它需要一個新的班級。

using System; 
using System.Data; 
using System.Drawing; 
using System.Windows.Forms; 

namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
      InitializeComboBox(); 
     } 

     private ComboxBoxEx cbox1 = new ComboxBoxEx(); 
     private DataTable items = new DataTable(); 

     private void InitializeComboBox() 
     { 
      items.Columns.AddRange(new DataColumn[] { new DataColumn("id"), new DataColumn("name"), new DataColumn("address") }); 

      items.Rows.Add(new object[] { 0, "[Please choose an address]", "" }); 
      items.Rows.Add(new object[] { 1, "Country", "Country" }); 
      items.Rows.Add(new object[] { 2, "House name", "House name\nStreet name\nTown name\nPostcode\nCountry" }); 
      items.Rows.Add(new object[] { 3, "House name", "House name\nStreet name\nTown name\nPostcode\nCountry" }); 

      cbox1.Location = new Point(39, 20); 
      cbox1.Size = new System.Drawing.Size(198, 21); 
      cbox1.DrawMode = DrawMode.OwnerDrawVariable; 
      cbox1.DrawItem += new DrawItemEventHandler(comboBox2_DrawItem); 
      cbox1.MeasureItem += new MeasureItemEventHandler(comboBox2_MeasureItem); 
      cbox1.SelectedIndexChanged += new EventHandler(comboBox2_SelectedIndexChanged); 
      //cbox1.DropDownWidth = 250; 
      //cbox1.DropDownHeight = 300; 
      //cbox1.MaxDropDownItems = 6; 
      this.Controls.Add(cbox1); 

      cbox1.ValueMember = "id"; 
      cbox1.DisplayMember = "name"; 
      cbox1.DataSource = new BindingSource(items, null); 
      //cbox1.SelectedIndex = -1; 
     } 

     private void comboBox2_MeasureItem(object sender, MeasureItemEventArgs e) 
     { 
      ComboxBoxEx cbox = (ComboxBoxEx)sender; 
      DataRowView item = (DataRowView)cbox.Items[e.Index]; 
      string txt = item["address"].ToString(); 

      int height = Convert.ToInt32(e.Graphics.MeasureString(txt, cbox.Font).Height); 

      e.ItemHeight = height + 4; 
      e.ItemWidth = cbox.DropDownWidth; 

      cbox.ItemHeights.Add(e.ItemHeight); 
     } 

     private void comboBox2_DrawItem(object sender, DrawItemEventArgs e) 
     { 
      ComboxBoxEx cbox = (ComboxBoxEx)sender; 
      DataRowView item = (DataRowView)cbox.Items[e.Index]; 
      string txt = item["address"].ToString(); 

      e.DrawBackground(); 
      e.Graphics.DrawString(txt, cbox.Font, System.Drawing.Brushes.Black, new RectangleF(e.Bounds.X + 2, e.Bounds.Y + 2, e.Bounds.Width, e.Bounds.Height)); 
      e.Graphics.DrawLine(new Pen(Color.LightGray), e.Bounds.X, e.Bounds.Top + e.Bounds.Height - 1, e.Bounds.Width, e.Bounds.Top + e.Bounds.Height - 1); 
      e.DrawFocusRectangle(); 
     } 

     private void comboBox2_SelectedIndexChanged(object sender, EventArgs e) 
     { 
      ComboxBoxEx cbox = (ComboxBoxEx)sender; 
      if (cbox.SelectedItem == null) return; 

      DataRowView item = (DataRowView)cbox.SelectedItem; 
      //label1.Text = item["id"].ToString(); 
     } 
    } 
} 

的ComboBoxEx類

using System; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 
using System.Collections.Generic; 

namespace WindowsFormsApplication1 
{ 
    public partial class ComboxBoxEx : ComboBox 
    { 
     [DllImport("user32.dll")] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect); 

     [DllImport("user32.dll", SetLastError = true)] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); 

     [StructLayout(LayoutKind.Sequential)] 
     public struct RECT 
     { 
      public int Left;  // x position of upper-left corner 
      public int Top;   // y position of upper-left corner 
      public int Right;  // x position of lower-right corner 
      public int Bottom;  // y position of lower-right corner 
     } 

     public const int SWP_NOZORDER = 0x0004; 
     public const int SWP_NOACTIVATE = 0x0010; 
     public const int SWP_FRAMECHANGED = 0x0020; 
     public const int SWP_NOOWNERZORDER = 0x0200; 

     public const int WM_CTLCOLORLISTBOX = 0x0134; 

     private int _hwndDropDown = 0; 

     internal List<int> ItemHeights = new List<int>(); 

     protected override void WndProc(ref Message m) 
     { 
      if (m.Msg == WM_CTLCOLORLISTBOX) 
      { 
       if (_hwndDropDown == 0) 
       { 
        _hwndDropDown = m.LParam.ToInt32(); 

        RECT r; 
        GetWindowRect((IntPtr)_hwndDropDown, out r); 

        int newHeight = 0; 
        int n = (Items.Count > MaxDropDownItems) ? MaxDropDownItems : Items.Count; 
        for (int i = 0; i < n; i++) 
        { 
         newHeight += ItemHeights[i]; 
        } 
        newHeight += 5; //to stop scrollbars showing 

        SetWindowPos((IntPtr)_hwndDropDown, IntPtr.Zero, 
         r.Left, 
           r.Top, 
           DropDownWidth, 
           newHeight, 
           SWP_FRAMECHANGED | 
            SWP_NOACTIVATE | 
            SWP_NOZORDER | 
            SWP_NOOWNERZORDER); 
       } 
      } 

      base.WndProc(ref m); 
     } 

     protected override void OnDropDownClosed(EventArgs e) 
     { 
      _hwndDropDown = 0; 
      base.OnDropDownClosed(e); 
     } 
    } 
}