WinForm自定义控件之AutoComplete

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

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

  

  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 }

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

  

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

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

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

  看看效果图:

  

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

  

时间: 2024-08-03 11:15:32

WinForm自定义控件之AutoComplete的相关文章

winform 自定义控件:半透明Loading控件

winform  自定义控件:半透明Loading控件 by wgscd date:2015-05-05 效果: using System;using System.Drawing;using System.Windows.Forms;using System.ComponentModel;using System.Threading; namespace wgscd{ /// <summary> /// 自定义控件:半透明控件 /// </summary> [ToolboxBit

(二十七)c#Winform自定义控件-多输入窗体

前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control 如果觉得写的还行,请点个 star 支持一下吧 欢迎前来交流探讨: 企鹅群568015492  准备工作 这个窗体继承子基类窗体FrmWithOKCancel1,如果你对FrmWithOKCancel1还不了解,请移步 (二十五)c#Winform自定义控件-有确定取消的窗体(一) 查看 开始 添

(四十一)c#Winform自定义控件-进度条

前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control 如果觉得写的还行,请点个 star 支持一下吧 欢迎前来交流探讨: 企鹅群568015492  NuGet Install-Package HZH_Controls 目录 https://www.cnblogs.com/bfyx/p/11364884.html 准备工作 前面写过一个进度条,但是并

c#Winform自定义控件-目录

前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git 如果觉得写的还行,请点个 star 支持一下吧 欢迎前来交流探讨: 企鹅群568015492  ~~~持续增加中~~~~~ 自定义控件 (一)c#Winform自定义控件-基类控件 (二

(四十六)c#Winform自定义控件-水波进度条

前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git 如果觉得写的还行,请点个 star 支持一下吧 欢迎前来交流探讨: 企鹅群568015492  麻烦博客下方点个[推荐],谢谢 NuGet Install-Package HZH_Con

(七十九)c#Winform自定义控件-导航菜单

前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git 如果觉得写的还行,请点个 star 支持一下吧 欢迎前来交流探讨: 企鹅群568015492  来都来了,点个[推荐]再走吧,谢谢 NuGet Install-Package HZH_C

WPF使用Winform自定义控件

在WPF的用户控件中使用Winfrom自定义控件的过程: 1.添加引用 WindowsFormsIntegration.dll System.Windows.Forms.dll 2.在要使用WinForm控件的WPF窗体的XAML文件中添加如下内容: xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" xmlns:wfi ="clr-namespace:System.Windo

winform 自定义控件的使用

c#的自定义控件还是很方便的,至少相对于c++而言. 1,当然是建立一个windows 窗体空间库,我这里就是用vs 2015 ,工程名MyControl 第二步.在自定义空间窗体内,拖放这样一组空间.我们发送编辑框的内容给父窗体,然后接受父窗体的发送的内容,显示到listbox 中. 这里会看到我使用了委托和事件,其实,刚入门的我,对于c#里的委托和事件 理解的并不深刻.看到很多地方再用.感觉和c++ 的回调很相似.这里就不纠结了, 后面慢慢理解吧.我们通过委托将子窗体的内容发送到主窗体. n

Winform自定义控件—Button(上)

在开发中用的最多的相信就是Button控件,但是Button本身是在是太丑陋了,自己还背景图还会产生"黑线",为了使用方便,并且美观,我们采用迂回的方式来实现Button的效果. 在这里使用UserControl+Label进行封装 先来看代码: ButtonM.cs 1 using System; 2 using System.ComponentModel; 3 using System.Drawing; 4 using System.Windows.Forms; 5 6 names