1、前言web
又臨近春節,做爲屌絲的我,又要爲車票發愁了。記得去年出現了各類12306的插件,最近不忙,因而也着手本身寫個搶票插件,當是熟悉一下WinForm吧。小軟件還在開發中,待完善後,也寫篇博客與你們分享。今天咱們的重點不是搶票軟件,而是其中的一點功能。咱們在買票的時候選站點的自動補全以下圖:
這功能在WinForm裏用什麼控件來實現呢?數組
1、自帶控件 網絡
WinForm裏面的ComBoBox 和TextBox 實際上是有自帶的自動補全功能的,咱們只須要將設置相應的屬性:
一、將 AutoCompleteSource 屬性設置爲 ListItems 或 CustomerSource (textbox 沒有 ListItems)
二、設置 AutoCompleteMode 自動完成樣式屬性設置,有三值 Suggest(顯示相關下拉)、append(自動補全相關)、suggestappend(前二者的結合),這個能夠自行試驗下。
三、而後設置 綁定 控件的 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的。是的,這樣能夠實現自動提示,而且也能在選中提示的某項時,取到顯示的值和實際值。可是這種方式至少有兩個缺點:
一、像購票的站點這種,數據量很大,有2k多條吧,你一次全綁定到ComboBox上?數據量太大,它沒有提供相應的事件來過濾數據。
二、多種搜索方式怎麼辦?中文、拼音、實際值、都是是能夠用來作輸入提示的關鍵字的。
其實以上兩點就是應爲 沒有提供相應的事件來處理 「搜索」。app
2、TextBox+ListBox 自定義AutoCompleteide
其實我能夠用 TextBox來得到用戶的輸入,而後動態控制ListBox。下面就按我作的思路一步步來實現一個自定義AutoComplete。this
一、監聽 textbox的 keyUp事件,得到用戶輸入
spa
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 }
二、監聽 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 }
三、監聽 ListBox 控件的鼠標移動事件
code
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都是能夠的,靈活性很大,只要按這個思路來就能夠。orm
3、一些第三方控件
固然網絡上也有一些很是好的相似AutoComplete的第三方控件,這裏我就不一一列出來了,由於我沒有找到合適的,呵呵!若是有人用過好的,歡迎在評論中分享,謝謝!
最後附上Demo的源碼:點擊這裏下載!
demo截圖:
如發現文中有誤,或有更好的建議,歡迎指出!