zoukankan      html  css  js  c++  java
  • 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截图:


    如发现文中有误,或有更好的建议,欢迎指出!

  • 相关阅读:
    The EF 6.x DbContextGenerator templates are not available for VS2010
    selenium定位tr及td,并获取其文本及属性
    selenium基本操作
    Git入门
    独热编码OneHotEncoder简介
    openCV中直方图均衡化算法的理解
    pyinstaller生成exe文件失败
    图像形态学运算
    对双边滤波的理解
    PyQt中对RadioButton分组
  • 原文地址:https://www.cnblogs.com/joey0210/p/3426394.html
Copyright © 2011-2022 走看看