using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms.ComponentModel; using System.Windows.Forms; using System.Drawing; using System.ComponentModel; using System.Collections; namespace CustomControl { public class AutoCompleteCombobox : ComboBox { private Form form; private int _sellstboxheight = 146; private Panel _dragPanel; private int _dragPanelSize = 5; private ListBox _sellistbox; private object _sourceList; private string _valueField; private string _displayField; private Color _dragPanelBackColor = Color.Black; private bool isClick = false; private Point startPoint = new Point(0, 0); private Point endPoint = new Point(0, 0); private Rectangle rect = new Rectangle(0, 0, 0, 0); private List<Data> sList = new List<Data>(); private Data curData; private bool isOnLBClick = false; private ToolTip _tip=new ToolTip (); public ToolTip Tip { get { return _tip; } set { _tip.SetToolTip(this, TipText); } } private string _tipText="不包含此输入项!"; public string TipText { get { return _tipText; } set { _tipText = value; } } public AutoCompleteCombobox() { this.KeyUp += new KeyEventHandler(AutoCompleteCombobox_KeyUp); this.DropDown += new EventHandler(AutoCompleteCombobox_DropDown); this.LostFocus += new EventHandler(AllLostFocus); this.KeyDown += new KeyEventHandler(AutoCompleteCombobox_KeyDown); this.SelectedIndexChanged += new EventHandler(AutoCompleteCombobox_SelectedIndexChanged); } void AutoCompleteCombobox_TextChanged(object sender, EventArgs e) { SearchItemsBack(); } public object SourceList { get { return _sourceList; } set { if (value == null) { return; } if (value is IEnumerable) { _sourceList = value; SetDataList(); DataSource = sList; } else { throw new Exception("请使用List对SourceList赋值!"); } } } /// <summary> /// 返回当前Text对应的Value值,如果Text不属于传入的List集合,则返回-- /// </summary> public string NewValue { get { if (Text.Trim() == string.Empty) return ""; else if (CheckText()) return curData.Value; else return "--"; } } public string NewText { get { return this.Text; } } public string ValueField { get { return _valueField; } set { _valueField = value; } } public string DisplayField { get { return _displayField; } set { _displayField = value; } } private bool SelVisible { get { return SelListBox.Visible && DragPanel.Visible; } set { SelListBox.Visible = value; DragPanel.Visible = value; } } [Category("样式")] [Description("拖拽块边长")] public int DragPanelSize { get { return _dragPanelSize; } set { _dragPanelSize = value; } } [Category("样式")] [Description("拖拽块背景色,默认为黑色")] public Color DragPanelBackColor { get { return _dragPanelBackColor; } set { _dragPanelBackColor = value; } } [Category("样式")] [Description("智能提示框高度,默认为146")] public int SelLstBoxHeight { get { return _sellstboxheight; } set { _sellstboxheight = value; } } public ListBox SelListBox { get { if (_sellistbox == null) { _sellistbox = new ListBox(); SelListBoxInitSetting(); _sellistbox.LostFocus += new EventHandler(AllLostFocus); _sellistbox.SelectedIndexChanged += new EventHandler(_sellistbox_SelectedIndexChanged); _sellistbox.KeyDown += new KeyEventHandler(_sellistbox_KeyDown); _sellistbox.MouseDown += new MouseEventHandler(_sellistbox_MouseDown); _sellistbox.MouseUp += new MouseEventHandler(_sellistbox_MouseUp); _sellistbox.Visible = false; _sellistbox.BringToFront(); } return _sellistbox; } } void form_MouseClick(object sender, MouseEventArgs e) { this.SelVisible = false; } void AutoCompleteCombobox_SelectedIndexChanged(object sender, EventArgs e) { curData = this.SelectedItem as Data; } void AutoCompleteCombobox_KeyDown(object sender, KeyEventArgs e) { //当智能提示框为显示状态时,屏蔽Combobox本身的keydown事件 if (SelVisible) { e.Handled = true; } switch (e.KeyData) { case Keys.Down: if (SelVisible && SelListBox.Items.Count > 0) { if (SelListBox.SelectedIndex == SelListBox.Items.Count - 1) SelListBox.SelectedIndex = 0; else SelListBox.SelectedIndex += 1; } break; case Keys.Up: if (SelVisible && SelListBox.Items.Count > 0) { if (SelListBox.SelectedIndex == 0) this.Focus(); else SelListBox.SelectedIndex -= 1; } break; case Keys.Enter: if (SelVisible) { curData = SelListBox.SelectedItem as Data; this.Text = curData.Text; SetCursorEnd(Text); SelVisible = false; } break; default: break; } } void _sellistbox_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { this.Text = ((Data)this._sellistbox.SelectedItem).Text; isOnLBClick = false; this.SelVisible = false; } } void _sellistbox_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { isOnLBClick = true; } } void _sellistbox_KeyDown(object sender, KeyEventArgs e) { switch (e.KeyData) { case Keys.Enter: if (SelVisible) { this.Text = SelListBox.Text; SelVisible = false; } break; default: break; } } public Panel DragPanel { get { if (_dragPanel == null) { _dragPanel = new Panel(); DragPanelInitSetting(); _dragPanel.MouseDown += new MouseEventHandler(_dragPanel_MouseDown); _dragPanel.MouseMove += new MouseEventHandler(_dragPanel_MouseMove); _dragPanel.MouseUp += new MouseEventHandler(_dragPanel_MouseUp); _dragPanel.LostFocus += new EventHandler(AllLostFocus); _dragPanel.BringToFront(); } return _dragPanel; } } /// <summary> /// 判断combobox上的文字是否属于传入的List /// </summary> /// <returns></returns> private bool CheckText() { bool flag = false; foreach (Data var in sList) { if (var.Text == Text) { flag = true; break; } } return flag; } void _sellistbox_SelectedIndexChanged(object sender, EventArgs e) { } /// <summary> /// 将光标位置移到文本结尾 /// </summary> /// <param name="text"></param> private void SetCursorEnd(string text) { this.SelectionStart = text.Length; this.SelectionLength = 0; } /// <summary> /// 将数据源转换为List(Data)类型 /// </summary> private void SetDataList() { sList = new List<Data>(); Data data; IEnumerable list = SourceList as IEnumerable; foreach (object var in list) { data = new Data(); data.Text = var.GetType().GetProperty(DisplayField).GetValue(var, null).ToString(); data.Value = var.GetType().GetProperty(ValueField).GetValue(var, null).ToString(); sList.Add(data); } //Data类的属性,再次写死 ValueMember = "Value"; DisplayMember = "Text"; } /// <summary> /// 拖拽块初始设置 /// </summary> private void DragPanelInitSetting() { SetPanelLocation(); _dragPanel.Width = DragPanelSize; _dragPanel.Height = DragPanelSize; _dragPanel.BackColor = DragPanelBackColor; _dragPanel.Cursor = Cursors.SizeNWSE; _dragPanel.TabStop = false; } /// <summary> /// 选项框初始设置 /// </summary> private void SelListBoxInitSetting() { if (form == null) { form = FindForm(); if (form != null) { SetForm(); } } _sellistbox.Location = new Point(this.Location.X, this.Location.Y + this.Height); _sellistbox.Width = this.Width; _sellistbox.Height = _sellstboxheight; _sellistbox.ImeMode = ImeMode.KatakanaHalf; _sellistbox.BorderStyle = BorderStyle.FixedSingle; _sellistbox.TabStop = false; if (form != null) { ComputeLocation(this, _sellistbox); _sellistbox.Parent = form; _sellistbox.BringToFront(); } } private void SetForm() { form.MouseClick += new MouseEventHandler(form_MouseClick); } /// <summary> /// 递归设置控件的location /// </summary> /// <param name="pc">父控件</param> /// <param name="setpc">需要设置的控件</param> private void ComputeLocation(Control pc, Control setpc) { if (pc.Parent != form) { if (pc != this) { setpc.Location = new Point(setpc.Location.X + pc.Left, setpc.Location.Y + pc.Top); } ComputeLocation(pc.Parent, setpc); } else { setpc.Location = new Point(setpc.Location.X + pc.Left, setpc.Location.Y + pc.Top); } } private void SetPanelLocation() { _dragPanel.Location = new Point(SelListBox.Location.X + SelListBox.Width, SelListBox.Location.Y + SelListBox.Height); _dragPanel.Parent = form; SetFromCtlClick(); } private void SetFromCtlClick() { if (form!=null) { foreach (Control ctl in form.Controls) { if (ctl!=this&&ctl!=SelListBox&&ctl!=DragPanel) { ctl.Click += new EventHandler(ctl_Click); } } } } void ctl_Click(object sender, EventArgs e) { this.SelVisible = false; } void AutoCompleteCombobox_KeyUp(object sender, KeyEventArgs e) { if (form == null) { form = FindForm(); SetForm(); } switch (e.KeyData) { case Keys.Up: break; case Keys.Down: break; case Keys.Enter: break; case Keys.Back: SearchItemsBack(); break; default: SearchItemsBack(); break; } this.TextChanged += new EventHandler(AutoCompleteCombobox_TextChanged); this.KeyUp -= AutoCompleteCombobox_KeyUp; } private void SearchItemsBack() { ListBox lb = SelListBox; Panel panel = DragPanel; if (!isOnLBClick) { string temp = Text; List<Data> tempList = new List<Data>(); if (temp == string.Empty) { tempList = sList; } else { foreach (Data data in sList) { if (data.Text.StartsWith(this.Text)) { tempList.Add(data); } } } if (tempList.Count == 1 && temp == tempList[0].Text) { return; } SelListBox.DataSource = tempList; SelListBox.ValueMember = "Value"; SelListBox.DisplayMember = "Text"; if (tempList.Count > 0) SelVisible = true; else { this.Tip.Show(TipText, form, SelListBox.Location.X+this.Width/2, SelListBox.Location.Y, 1000); SelVisible = false; } } } /// <summary> /// 自动补齐 /// </summary> /// <param name="temp"></param> /// <param name="tempList"></param> private void AutoComplete(string temp, List<Data> tempList) { if (tempList.Count > 0) { if (temp != string.Empty) { curData = (Data)SelListBox.SelectedItem; this.Text = curData.Text; this.Focus(); if (Text.Length > temp.Length) { this.Select(temp.Length, Text.Replace(temp, "").Length); } else { this.SelectionStart = temp.Length; this.SelectionLength = 0; } SelVisible = true; } else { SelListBox.SelectedIndex = 0; Text = string.Empty; } } else SelVisible = false; } void AutoCompleteCombobox_DropDown(object sender, EventArgs e) { SelVisible = false; } void AllLostFocus(object sender, EventArgs e) { ListBox lb = SelListBox; Panel panel = DragPanel; if (lb.Focused == false && panel.Focused == false && this.Focused == false) { SelVisible = false; } } void _dragPanel_MouseUp(object sender, MouseEventArgs e) { isClick = false; ListBox lb = SelListBox; lb.Width = rect.Width; lb.Height = rect.Height; SetPanelLocation(); rect = new Rectangle(0, 0, 0, 0); ControlPaint.DrawReversibleFrame(rect, this.BackColor, FrameStyle.Dashed); form.Refresh(); } void _dragPanel_MouseMove(object sender, MouseEventArgs e) { if (isClick) { startPoint = form.PointToScreen(SelListBox.Location); endPoint = form.PointToScreen(new Point(e.X + DragPanel.Left, e.Y + DragPanel.Top)); int width = endPoint.X - startPoint.X; int height = endPoint.Y - startPoint.Y; if (!(width <= 0 || height <= 0)) { ControlPaint.DrawReversibleFrame(rect, this.BackColor, FrameStyle.Dashed); SelListBox.Refresh(); rect = new Rectangle(startPoint, new Size(width, height)); ControlPaint.DrawReversibleFrame(rect, this.BackColor, FrameStyle.Dashed); } } } void _dragPanel_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { isClick = true; } } } public class Data { //更改此类的属性名称的同时需修改SetDataList方法 private string _text; public string Text { get { return _text; } set { _text = value; } } private string _value; public string Value { get { return _value; } set { _value = value; } } } } 调用 List<Data> list = new List<Data>(); Data d; for (int i = 50; i < 400; i++) { d = new Data(); d.ID = i.ToString(); d.Value = i.ToString(); list.Add(d); } object obj = list; this.autoCompleteCombobox1.ValueField = "ID"; this.autoCompleteCombobox1.DisplayField = "Value"; this.autoCompleteCombobox1.SourceList = obj;