3

我试图找出从选择列表中填充地址字段的最佳方法(含糊但请继续阅读)..

布局:

在此处输入图像描述

当我选择地址下拉列表时,我希望看到一个完整地址的列表,例如街道名称、国家、邮政编码等,但我相信您知道,组合只是一个衬垫。

理想场景:

在此处输入图像描述

结果:

在此处输入图像描述

有没有人这样做的方法?

4

1 回答 1

8

这是完整的解决方案,如您所见,它完全符合我的要求。

在此处输入图像描述

ComboBoxEx 是一个派生自我上次复制的 ComboBox 的类。其原因是设置Items容器的高度(DropDownHeight)。没有它,容器将根据第一个项目的大小 x 不计算。项目,并且由于第一个项目的高度为零,因此容器的高度为零。所以它需要一个新的类。

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);
        }
    }
}
于 2012-09-14T18:35:05.390 回答