转载

WinForm自定义控件之AutoComplete

关于TextBox的AutoComplete功能断断续续搞了一段时间,之前写过几个类似的自定义控件,包括TextBox自带的,但是效果不是很好。刚好项目需要,结合原来的思路重新写了一个相对比较好用的版本。

废话不多说,直接贴代码吧。下拉的控件我用的DevExpress的GridControl,比较美观。可以根据自己的需要改成DataGridView或者ListView。

WinForm自定义控件之AutoComplete
  1 using System;   2 using System.Collections.Generic;   3 using System.ComponentModel;   4 using System.Data;   5 using System.Drawing;   6 using System.Linq;   7 using System.Text;   8 using System.Windows.Forms;   9 using DevExpress.XtraGrid;  10 using DevExpress.XtraGrid.Views.Grid;  11   12 namespace TestAutoComplete  13 {  14     public partial class AutoTextBoxNew : TextBox  15     {  16         private string[] _keys;  17         private SearchMode _searchMode;  18         private List<BaseItem> items = new List<BaseItem>();  19         private GridView _view;  20         private GridControl _grid;  21         private int _gvWidth = 200;  22         private int _gvHeight = 200;  23         private DataTable _dtlData = null;//绑定的数据源  24         private Control _form;  25         private string _needValue;  26         private string _needName;  27         private bool _isSearch = true;  28         private bool _isShowAllData = false;  29   30         #region 属性  31         [TypeConverter(typeof(System.ComponentModel.CollectionConverter))]  32         [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]  33         [Category("样式")]  34         [Description("绑定列")]  35         public List<BaseItem> Items  36         {  37             get  38             { return items; }  39         }  40   41         [Category("样式")]  42         [Description("模糊查找关键字")]  43         public string[] SearchKey  44         {  45             get { return _keys;}  46             set { _keys = value; }  47         }  48   49         [Category("样式")]  50         [Description("赋值在文本框的tag里,对应数据源的字段名称")]  51         public string NeedValue  52         {  53             get { return _needValue; }  54             set { _needValue = value; }  55         }  56   57         [Category("样式")]  58         [Description("赋值在文本框上的内容,对应数据源的字段名称")]  59         public string NeedName  60         {  61             get { return _needName; }  62             set { _needName = value; }  63         }  64   65         [Category("样式")]  66         [Description("模糊查找的方式,有左模糊、右模糊、全模糊")]  67         public SearchMode SearchModel  68         {  69             get { return _searchMode; }  70             set  71             {  72                 _searchMode = value;  73             }  74         }  75   76         [Category("样式")]  77         [Description("GridView宽度")]  78         public int GridViewWidth  79         {  80             get { return _gvWidth; }  81             set  82             {  83                 _gvWidth = value;  84             }  85         }  86   87         [Category("样式")]  88         [Description("GridView高度")]  89         public int GridViewHeight  90         {  91             get { return _gvHeight; }  92             set  93             {  94                 _gvHeight = value;  95             }  96         }  97   98         [Category("样式")]  99         [Description("当未输入查询条件时是否全显示数据")] 100         public bool IsShowAllData 101         { 102             get { return _isShowAllData; } 103             set 104             { 105                 _isShowAllData = value; 106             } 107         } 108  109         #endregion 110  111         /// <summary> 112         /// 构造函数 113         /// </summary> 114         public AutoTextBoxNew() 115         { 116             InitializeComponent(); 117             _grid = new GridControl(); 118         } 119  120         /// <summary> 121         /// 初始化 122         /// </summary> 123         /// <param name="dtlSource"></param> 124         public void Init(DataTable dtlSource) 125         { 126             _dtlData = dtlSource; 127             initListView(); 128         } 129  130         /// <summary> 131         /// 初始化GridView 132         /// </summary> 133         private void initListView() 134         { 135             if (items != null) 136             { 137                 try 138                 { 139                     _view = new GridView(); 140                     _view.OptionsView.ShowGroupPanel = false; 141                     _view.OptionsBehavior.Editable = false; 142                     _view.OptionsView.ColumnAutoWidth = false; 143                     _grid.KeyDown += new KeyEventHandler(_grid_KeyDown); 144                     _grid.MouseDoubleClick += new MouseEventHandler(_grid_MouseDoubleClick); 145                     _grid.Leave += new EventHandler(_grid_Leave); 146                     foreach (BaseItem item in items) 147                     { 148                         DevExpress.XtraGrid.Columns.GridColumn col = new DevExpress.XtraGrid.Columns.GridColumn(); 149  150                         col.FieldName = item.FieldCode; 151                         col.Caption = item.DisplayName; 152                         col.Width = item.ColumnWidth == 0 ? 100 : item.ColumnWidth; 153                         col.Visible = true; 154                         _view.Columns.Add(col); 155                     } 156                     _grid.MainView = _view; 157                     _grid.Width = _gvWidth; 158                     _grid.Height = _gvHeight; 159                     _form = this.Parent; 160                     while (true) 161                     { 162                         if (_form.Parent == null) break; 163                         _form = _form.Parent; 164                     } 165                     _grid.Location = _form.PointToClient(this.Parent.PointToScreen(new Point(this.Left, this.Top + this.Height + 3))); 166                     _form.Controls.Add(_grid); 167                     _grid.Visible = false; 168                 } 169                 catch 170                 { 171   172                 } 173             } 174         } 175  176         /// <summary> 177         /// GridView焦点离开 178         /// </summary> 179         /// <param name="sender"></param> 180         /// <param name="e"></param> 181         public void _grid_Leave(object sender, EventArgs e) 182         { 183             if (!this.Focused) 184             { 185                 _grid.Visible = false; 186             } 187         } 188  189         /// <summary> 190         /// GridView双击事件,赋值 191         /// </summary> 192         /// <param name="sender"></param> 193         /// <param name="e"></param> 194         public void _grid_MouseDoubleClick(object sender, MouseEventArgs e) 195         { 196             if (_view.FocusedRowHandle >= 0) 197             { 198                 _isSearch = false; 199                 this.Tag = _view.GetFocusedRowCellValue(_needValue).ToString(); 200                 this.Text = _view.GetFocusedRowCellValue(_needName).ToString(); 201                 _grid.Visible = false; 202             } 203         } 204  205         /// <summary> 206         /// GridView回车事件,赋值 207         /// </summary> 208         /// <param name="sender"></param> 209         /// <param name="e"></param> 210         public void _grid_KeyDown(object sender, KeyEventArgs e) 211         { 212             if (e.KeyCode == Keys.Enter) 213             { 214                 if (_view.FocusedRowHandle >= 0) 215                 { 216                     _isSearch = false; 217                     this.Tag = _view.GetFocusedRowCellValue(_needValue).ToString(); 218                     this.Text = _view.GetFocusedRowCellValue(_needName).ToString(); 219                     _grid.Visible = false; 220                 } 221             } 222         } 223  224         protected override void OnPaint(PaintEventArgs pe) 225         { 226             base.OnPaint(pe); 227         } 228  229         protected override void OnTextChanged(EventArgs e) 230         { 231             if (this.Text != "") 232             { 233                 if (_isSearch) 234                 { 235                     DataTable dt = Search(this.Text); 236                     _grid.DataSource = dt; 237                     _grid.Visible = true; 238                     _grid.BringToFront(); 239                 } 240                 else 241                 { 242                     _isSearch = true; 243                 } 244                  245             } 246             else 247             { 248                 if (_isShowAllData) 249                 { 250                     _grid.DataSource = _dtlData; 251                     _grid.Visible = true; 252                     _grid.BringToFront(); 253                 } 254                 else 255                 { 256                     _grid.Visible = false; 257                 } 258             } 259             base.OnTextChanged(e); 260         } 261  262         protected override void OnKeyDown(KeyEventArgs e) 263         { 264             if (e.KeyCode == Keys.Down) 265             { 266                 _grid.Focus(); 267             } 268             else if (e.KeyCode == Keys.Enter) 269             { 270                 if (_grid.DataSource != null) 271                 { 272                     _isSearch = false; 273                     this.Tag = _view.GetRowCellValue(0, _needValue).ToString(); 274                     this.Text = _view.GetRowCellValue(0, _needName).ToString(); 275                     _grid.Visible = false; 276                 } 277             } 278             base.OnKeyDown(e); 279         } 280  281         /// <summary> 282         /// 检索 283         /// </summary> 284         /// <param name="keyvalue"></param> 285         /// <returns></returns> 286         private DataTable Search(string keyvalue) 287         { 288             DataTable dtlReturn = null; 289             if (_dtlData != null && _keys.Length > 0) 290             { 291                 string filters = ""; 292                 foreach (string str in _keys) 293                 { 294                     switch (_searchMode) 295                     { 296                         case SearchMode.Left: 297                             filters += "or " + str + " like'%" + keyvalue + "' "; 298                             break; 299                         case SearchMode.Right: 300                             filters += "or " + str + " like'" + keyvalue + "%' "; 301                             break; 302                         case SearchMode.All: 303                             filters += "or " + str + " like'%" + keyvalue + "%' "; 304                             break; 305                     } 306                 } 307                 filters = filters.Substring(2, filters.Length - 2); 308                 DataRow[] dr = _dtlData.Select(filters); 309                 if (dr.Length > 0) 310                 { 311                     dtlReturn = dr.CopyToDataTable(); 312                 } 313             } 314             return dtlReturn; 315         } 316  317         /// <summary> 318         /// 焦点离开隐藏起来 319         /// </summary> 320         /// <param name="e"></param> 321         protected override void OnLeave(EventArgs e) 322         { 323             if (!_grid.IsFocused) 324             { 325                 _grid.Visible = false; 326             } 327             base.OnLeave(e); 328         }  329  330     } 331  332     public class BaseItem 333     { 334         public string DisplayName 335         { get; set; } 336         public string FieldCode 337         { get; set; } 338         public int ColumnWidth 339         { get; set; } 340     } 341  342     public enum SearchMode { Left, Right, All } 343 }
View Code

调用比较简单,需要配置一些属性,如图:

WinForm自定义控件之AutoComplete WinForm自定义控件之AutoComplete

Items主要设置需要显示哪些列,NeedName与NeedValue必须配置一下,赋值的时候需要用到。

最后调用一下初始化的方法把数据源传入就OK了

autoTextBoxNew1.Init(ds.Tables[0]);

看看效果图:

WinForm自定义控件之AutoComplete

本人才疏学浅,如发现文中有误欢迎交流指出

正文到此结束
Loading...