WinForm AutoComplete 輸入提示、自動補全


一、前言

  又臨近春節,作為屌絲的我,又要為車票發愁了。記得去年出現了各種12306的插件,最近不忙,於是也着手自己寫個搶票插件,當是熟悉一下WinForm吧。小軟件還在開發中,待完善后,也寫篇博客與大家分享。今天我們的重點不是搶票軟件,而是其中的一點功能。我們在買票的時候選站點的自動補全如下圖:

這功能在WinForm里用什么控件來實現呢?

一、自帶控件  

  WinForm里面的ComBoBox 和TextBox 其實是有自帶的自動補全功能的,我們只需要將設置相應的屬性:
       1、將  AutoCompleteSource 屬性設置為 ListItems 或 CustomerSource (textbox 沒有 ListItems)
         2、設置 AutoCompleteMode  自動完成樣式屬性設置,有三值 Suggest(顯示相關下拉)、append(自動補全相關)、suggestappend(前兩者的結合),這個可以自行試驗下。
         3、然后設置 綁定 控件的 DataSource 或 AutoCompleteCustomSource。
     
AutoCompleteSource屬性設置的是 CustomerSource 的時候我們需要綁定 AutoCompleteCustomSource屬性的值,值為一個string類型的數組:
                     this.cbbEndStation.AutoCompleteCustomSource.AddRange(new string[] { "站點1", "站點2", "站點3", "站點4" });

      這樣ComBoBox 和 TextBox 就有輸入提示功能了。至此,不知道大家有沒有發現問題,這里綁定的數據只有 顯示的值,而沒有 實際的值,一般像這種控件,我們都是有一個顯示值和一個實際值的。有人可能會說,使用ComBoBox 控件,然后將AutoCompleteSource設置為ListItems,提示的就是DataSource里的值了,而DataSource是可以綁定 集合,設置DisplayMember和ValueMember的。是的,這樣可以實現自動提示,並且也能在選中提示的某項時,取到顯示的值和實際值。但是這種方式至少有兩個缺點:

         1、像購票的站點這種,數據量很大,有2k多條吧,你一次全綁定到ComboBox上?數據量太大,它沒有提供相應的事件來過濾數據。

         2、多種搜索方式怎么辦?中文、拼音、實際值、都是是可以用來做輸入提示的關鍵字的。

     其實以上兩點就是應為 沒有提供相應的事件來處理 “搜索”

二、TextBox+ListBox 自定義AutoComplete

      其實我可以用 TextBox來獲得用戶的輸入,然后動態控制ListBox。下面就按我做的思路一步步來實現一個自定義AutoComplete。

      1、監聽 textbox的 keyUp事件,獲得用戶輸入

 1         /// <summary>
 2         /// 站點文本框 鍵盤按下松開事件
 3         /// </summary>
 4         /// <param name="sender"></param>
 5         /// <param name="e"></param>
 6         private void txtStation_KeyUp(object sender, KeyEventArgs e)
 7         {
 8             TextBox eObj = sender as TextBox; //事件源對象
 9             txtStation_Name = eObj; //當前事件出發對象
10             if (eObj.Name == "txtStation_S_Name")
11             {
12                 txtStation_Value = this.txtStation_S_Value; //保存值的textbox
13                 ltb_Stations = this.lb_Start_Stations;   //始發站 展示數據的
14             }
15             else
16             {
17                 //到站 控件
18                 txtStation_Value = this.txtStation_E_Value; //保存值的textbox
19                 ltb_Stations = this.lb_End_Stations;   //始發站 展示數據的
20             }
21             //上下左右
22             if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Left)
23             {
24                 if (ltb_Stations.SelectedIndex > 0)
25                     ltb_Stations.SelectedIndex--;
26             }
27             else if (e.KeyCode == Keys.Down || e.KeyCode == Keys.Right)
28             {
29                 if (ltb_Stations.SelectedIndex < ltb_Stations.Items.Count - 1)
30                     ltb_Stations.SelectedIndex++;
31             }
32             //回車
33             else if (e.KeyCode == Keys.Enter)
34             {
35                 StationInfo info = ltb_Stations.SelectedItem as StationInfo;
36                 txtStation_Name.Text = info.StationName_CN;
37                 txtStation_Value.Text = info.StationValue;
38                 ltb_Stations.Visible = false;
39             }
40             else
41             {
42 
43                 if (txtStation_Name.Text != "")
44                 {
45                     IList<StationInfo> dataSource = StationInfo.GetStations(txtStation_Name.Text.Trim());
46                     if (dataSource.Count > 0)
47                     {
48                         ltb_Stations.DataSource = dataSource;
49                         ltb_Stations.DisplayMember = "StationName_CN";
50                         ltb_Stations.ValueMember = "StationValue";
51                         ltb_Stations.Visible = true;
52                     }
53                     else
54                         ltb_Stations.Visible = false;
55                 }
56                 else
57                 {
58                     ltb_Stations.Visible = false;
59                 }
60             }
61             txtStation_Name.Select(txtStation_Name.Text.Length, 1); //光標定位到文本框最后
62         }
View Code


      2、監聽 ListBox 控件的點擊事件
      

 1         /// <summary>
 2         /// 展示站點列表的listbox的點擊事件,為了給textbox賦值
 3         /// </summary>
 4         /// <param name="sender"></param>
 5         /// <param name="e"></param>
 6         private void ListBox_StationDatas_Click(object sender, EventArgs e)
 7         {
 8             ListBox eObj = sender as ListBox;
 9             StationInfo info = eObj.SelectedItem as StationInfo;
10             txtStation_Name.Text = info.StationName_CN;
11             txtStation_Value.Text = info.StationValue;
12             eObj.Visible = false;
13             txtStation_Name.Select(txtStation_Name.Text.Length, 1); //光標定位到最后
14         }


      3、監聽 ListBox 控件的鼠標移動事件

 1          /// <summary>
 2          /// 展示站點列表的listbox, 鼠標在該控件上移動事件,
 3       /// 為了鼠標移動選項
 4       /// </summary>
 5         /// <param name="sender"></param>
 6         /// <param name="e"></param>
 7         private void ListBox_StationDatas_MouseMove(object sender, MouseEventArgs e)
 8         {
 9             ListBox eObj = sender as ListBox;
10             eObj.SelectedIndex = eObj.IndexFromPoint(e.Location);
11         }

 

以上三步就可以完成一個自定義 AutoComplete的功能了,為什么要叫自定義呢?因為我們在 監聽 TextBox 的輸入時,可以自定義搜索規則,還有我們可以將ListBox換成 DataGridView都是可以的,靈活性很大,只要按這個思路來就可以。

三、一些第三方控件

     當然網絡上也有一些非常好的類似AutoComplete的第三方控件,這里我就不一一列出來了,因為我沒有找到合適的,呵呵!如果有人用過好的,歡迎在評論中分享,謝謝!

最后附上Demo的源碼:點擊這里下載!
demo截圖:


如發現文中有誤,或有更好的建議,歡迎指出!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM