C# Winform ComboBox 在输入内容时 会在下拉菜单中显示 根据输入内容查询的结果

本文转载于 http://zhidao.baidu.com/question/180144652.html


C# Winform ComboBox 在输入内容时 会在下拉菜单中显示 根据输入内容查询的结果

2010-9-1 10:57
提问者: wangpeng468 | 浏览次数:3653次
C# ComboBox 在输入内容时 会在下拉菜单中显示 根据输入内容查询的结果,而且下拉菜单一直是展开的?如何实现?就是百度Google输入内容 下拉菜单出自动出现结果的那种效果?

问题补充:

对了 还有,我还想让他能自动检索拼音首字母,获得拼音首字母的方法我清楚,但是这种
设置ComboBox属性AutoCompleteCustomerSource和AutoCompleteMode方法
无法检索拼音首字母啊
我来帮他解答
检举 | 2010-9-1 16:40
满意回答
将ComboBox的AutoCompleteMode属性置为SuggestAppend,AutoCompleteSource属性置为ListItems,然后给ComboBox随便塞几个子项,运行看效果。

扩展:
AutoCompleteMode允许有四种值:

None:默认值,指示ComboBox不使用自动功能。
Suggest:在ComboBox中输入字符后,ComboBox会自动展开,显示匹配的子项,输入行不受影响,需要自己输入后续字符,或者在下拉框中点选完整子项。
Append:输入字符后,字符后会自动补充匹配内容(以反色显示),但是ComboBox不会展开。按上下键可以在多个匹配内容中切换。
SuggestAppend:上述两种模式的组合。

AutoCompleteSource属性,共有9种,指示自动完成将要在其中进行查找的数据源。常用的几种如下:

ListItems:数据源为ComboBox的Item集合。
FileSystem:文件系统。例如输入c:\后会展开c:\下的目录列表(或append模式下的自动添加)。同样的,此数据源也支持文件名的补全。
CustomSource:自定义数据源。选用此方式时必须在代码中指定ComboBox的AutoCompleteCustomSource属性为你构建的AutoCompleteStringCollection对象,否则不会生效。AutoCompleteStringCollection类似于List<string>,将你的数据add进去即可。


[高质量编程]团队成员为您解答,请提出宝贵意见和建议。谢谢!
QQ:176229432 

补充回答:

首先我需要强调一点,使用拼音首字母检索时可能比较适合DropDownStyle=DropDownList时。
以下是我项目中一个控件库中的扩展组件完整代码,编译成组件丢到其他UI中,所有ComboBox和ListBox均会添加扩展属性SearchOnKeyEnable,置为true后自己看效果。加入了按键间隔判断,两次按键时间间隔短则认为是一个词的数个字的首字母,间隔时间长认为是其他词的首字。
另外要注意,使用时请关闭AutoComplete相关属性,同时置DropDownStyle=DropDownList效果最好。

此代码段仅供学习参考,望各位能自己写出更完善的代码而非直接拷贝使用。


using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;
using System.Data;

namespace !#你的命名空间#!
{
    /// <summary>
    /// ListControl扩展组件,使ListControl控件在按下键后能够自动搜索并定位到与按下键相匹配的项
    /// 如在按下“S”后能自动定位到“深圳”
    /// </summary>
    [ProvideProperty("SearchOnKeyPressedEnabled", typeof(ListControl))]
    public partial class ListControlExtender : Component, IExtenderProvider
    {
        #region 私有字段

        private Dictionary<ListControl, Properties> properties = new Dictionary<ListControl, Properties>(7);
        private StringBuilder sbKeys = new StringBuilder(10);
        private StringBuilder sbItem = new StringBuilder(50);
        private int twicePressKeyInterval = 500;       //两次按键时间间隔(单位:毫秒)

        private class Properties
        {
            public StringBuilder PressedKeys;       //按键
            public DateTime PrevPressKeyTime;       //上次按键时间
            public bool SearchOnKeyPressedEnabled;  //按键搜索是否激活

            public Properties()
            {
                this.PressedKeys = new StringBuilder(10);  
                this.PrevPressKeyTime = DateTime.Now;
                this.SearchOnKeyPressedEnabled = false;
            }
        }

        #endregion

        #region 构造函数

        public ListControlExtender()
        {
            InitializeComponent();
        }

        public ListControlExtender(IContainer container)
        {
            container.Add(this);

            InitializeComponent();
        }

        #endregion

        #region 接口方法 IExtenderProvider.CanExtend

        bool IExtenderProvider.CanExtend(object o)
        {
            if (o is ListControl)
            {
                return true;
            }
            return false;
        }

        #endregion

        #region 属性定义

        [Category("设置")]
        [Description("两次按键时间间隔(单位:毫秒)")]
        public int TwicePressKeyInterval
        {
            get
            {
                return this.twicePressKeyInterval;
            }
            set
            {
                this.twicePressKeyInterval = value > 0 ? value : 0;
            }
        }

        #endregion

        #region 私有函数

        /// <summary>
        /// 确保扩展属性的菜单项在字典中
        /// </summary>
        /// <param name="key">目标菜单项</param>
        /// <returns>扩展属性</returns>
        private Properties EnsurePropertiesExists(ListControl key)
        {
            Properties p;
            if (properties.ContainsKey(key))
            {
                p = properties[key];
            }
            else
            {
                p = new Properties();
                properties.Add(key, p);
            }
            return p;
        }

        /// <summary>
        /// 取得汉字字符的拼音首字母
        /// </summary>
        /// <param name="c">汉字字符</param>
        /// <returns>拼音首字母</returns>
        private string GetFristPYLetterOfChar(string c)
        {
            try
            {
                byte[] array = new byte[2];
                array = System.Text.Encoding.Default.GetBytes(c);
                int i = (short)(array[0] - '\0') * 256 + ((short)(array[1] - '\0'));
                //if (i < 0xB0A1) return "*";
                if (i < 0xB0C5) return "a";
                if (i < 0xB2C1) return "b";
                if (i < 0xB4EE) return "c";
                if (i < 0xB6EA) return "d";
                if (i < 0xB7A2) return "e";
                if (i < 0xB8C1) return "f";
                if (i < 0xB9FE) return "g";
                if (i < 0xBBF7) return "h";
                if (i < 0xBFA6) return "j";
                if (i < 0xC0AC) return "k";
                if (i < 0xC2E8) return "l";
                if (i < 0xC4C3) return "m";
                if (i < 0xC5B6) return "n";
                if (i < 0xC5BE) return "o";
                if (i < 0xC6DA) return "p";
                if (i < 0xC8BB) return "q";
                if (i < 0xC8F6) return "r";
                if (i < 0xCBFA) return "s";
                if (i < 0xCDDA) return "t";
                if (i < 0xCEF4) return "w";
                if (i < 0xD1B9) return "x";
                if (i < 0xD4D1) return "y";
                //if (i < 0xD7FA) return "z";
                return "z";
            }
            catch
            {
                return "*";
            }
        }

        /// <summary>
        /// 取得汉字字符串的拼音首字母
        /// </summary>
        /// <param name="str">汉字字符串</param>
        /// <returns>拼音首字母</returns>
        private string GetFirstPYLetterOfString(string str)
        {
            StringBuilder sb = new StringBuilder(100);
            foreach (char c in str)
            {
                //字母和符号原样保留
                if ((int)c >= 33 && (int)c <= 126)
                    sb.Append(c.ToString());
                else
                    sb.Append(GetFristPYLetterOfChar(c.ToString()));
            }
            return sb.ToString();
        }

        /// <summary>
        /// 将列表控件集合项转换为字符串
        /// </summary>
        /// <param name="listControl">列表控件</param>
        /// <param name="index">集合索引</param>
        /// <returns>转换后的字符串</returns>
        private string ConvertListControlItemToString(ListControl listControl, int index)
        {
            if (listControl is ComboBox)
            {
                //如果未绑定则直接转换为字符串
                if (listControl.DataSource == null)
                    return (string)(((ComboBox)listControl).Items[index]);
                else
                {
                    //如果绑定则转换为DataRowView后再取相应字段值
                    DataRowView view = (DataRowView)(((ComboBox)listControl).Items[index]);
                    if (((ComboBox)listControl).DisplayMember != null)
                        return Convert.ToString(view[((ComboBox)listControl).DisplayMember]);
                    else if (((ComboBox)listControl).ValueMember != null)
                        return Convert.ToString(view[((ComboBox)listControl).ValueMember]);
                    else
                        return "";
                }
            }
            else if (listControl is ListBox)
            {
                //如果未绑定则直接转换为字符串
                if (listControl.DataSource == null)
                    return (string)(((ListBox)listControl).Items[index]);
                else
                {
                    //如果绑定则转换为DataRowView后再取相应字段值
                    DataRowView view = (DataRowView)(((ListBox)listControl).Items[index]);
                    if (((ListBox)listControl).DisplayMember != null)
                        return Convert.ToString(view[((ListBox)listControl).DisplayMember]);
                    else if (((ListBox)listControl).ValueMember != null)
                        return Convert.ToString(view[((ListBox)listControl).ValueMember]);
                    else
                        return "";
                }
            }
            else
            {
                return "";
            }
        }

        /// <summary>
        /// 列表控件KeyPress事件处理函数
        /// </summary>
        /// <param name="sender">列表控件</param>
        /// <param name="e">参数</param>
        private void listControl_KeyPress(object sender, KeyPressEventArgs e)
        {
            ListControl listControl = (ListControl)sender;
            //清空按键字符串
            sbKeys.Remove(0, sbKeys.Length);
            //取得当前时间
            DateTime now = DateTime.Now;
            //取得与上次按下键时间差
            TimeSpan span = now - properties[listControl].PrevPressKeyTime;
            //如果两次按键时间差小于TwicePressKeyInterval,则认为是按下多个键
            if (span.TotalMilliseconds < twicePressKeyInterval)
            {
                properties[listControl].PressedKeys.Append(e.KeyChar.ToString());
                sbKeys.Append(properties[listControl].PressedKeys.ToString());
            }
            else //否则为按下一个键
            {
                sbKeys.Append(e.KeyChar.ToString());
                properties[listControl].PressedKeys.Remove(0,properties[listControl].PressedKeys.Length);
                properties[listControl].PressedKeys.Append(sbKeys.ToString());
            }
            //更新按键时间
            properties[listControl].PrevPressKeyTime = now;
            //记录初始索引值
            int oldIndex = listControl.SelectedIndex;
            int newIndex = oldIndex;
            //取得列表项个数
            int itemCount = 0;
            if (listControl is ComboBox)
                itemCount = ((ComboBox)listControl).Items.Count;
            else
                itemCount = ((ListBox)listControl).Items.Count;
            //先从当前位置向后搜索
            bool match = false;
            for (int i = oldIndex + 1; i < itemCount; i++)
            {
                //清空
                sbItem.Remove(0, sbItem.Length);
                //取得列表项字符串
                //改为调用将列表控件集合项转换为字符串方法 2007-08-13
                sbItem.Append(ConvertListControlItemToString(listControl, i));
                //比较按键与列表项首字母是否匹配
                if (sbKeys.Length < sbItem.Length)
                    match = GetFirstPYLetterOfString(sbItem.ToString()).IndexOf(sbKeys.ToString()) == 0;
                else
                    match = sbKeys.ToString().IndexOf(GetFirstPYLetterOfString(sbItem.ToString())) == 0;
                if (match)
                {
                    newIndex = i;
                    break;
                }
            }
            if ((newIndex == oldIndex) && (oldIndex > 0)) //未搜索到则从0开始搜索
            {
                for (int i = 0; i <= oldIndex; i++)
                {
                    //清空
                    sbItem.Remove(0, sbItem.Length);
                    //取得列表项字符串
                    //改为调用将列表控件集合项转换为字符串方法 2007-08-13
                    sbItem.Append(ConvertListControlItemToString(listControl, i));
                    //比较按键与列表项首字母是否匹配
                    if (sbKeys.Length < sbItem.Length)
                        match = GetFirstPYLetterOfString(sbItem.ToString()).IndexOf(sbKeys.ToString()) == 0;
                    else
                        match = sbKeys.ToString().IndexOf(GetFirstPYLetterOfString(sbItem.ToString())) == 0;
                    if (match)
                    {
                        newIndex = i;
                        break;
                    }
                }
            }
            listControl.SelectedIndex = newIndex;
        }

        #endregion

        #region 激活按下键时搜索功能

        [Description("是否激活按下键时搜索功能")]
        [Category("扩展")]
        public bool GetSearchOnKeyPressedEnabled(ListControl listControl)
        {
            Properties p = EnsurePropertiesExists(listControl);
            return p.SearchOnKeyPressedEnabled;
        }

        public void SetSearchOnKeyPressedEnabled(ListControl listControl, bool value)
        {
            Properties p = EnsurePropertiesExists(listControl);
            p.SearchOnKeyPressedEnabled = value;
            if (value)
                listControl.KeyPress += new KeyPressEventHandler(listControl_KeyPress);
            else
                listControl.KeyPress -= new KeyPressEventHandler(listControl_KeyPress);
        }

        #endregion
    }
}

最后,我还要指出一点,自动完成和首字母查询定位是不能混用的。
假设combobox子项为{"陕西","山东},当按下s键时,只可能展开combobox然后定位到"陕西",不可能也不应该同时更改combobox的显示字串。输入的s可以删掉,但是无法决定我是该添'陕'字还是该添'山'字进去。没法确定首字,也就没法使用自动添加/完成了。
所以在此我只能建议你使用经典方式,也就是上面代码实现的功能:dropdownlist,单击展开列表,按下键定位到合适的行;或者有焦点时直接输入拼音首字,在不展开列表的情况下直接填充。


有疑问请留言!



------------------------------------------------------------------------------------------------------------------------------------------

还可以参考 http://wenku.baidu.com/view/4f4581fb770bf78a65295467.html    

ComboBox



  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以使用以下步骤在C# WinForm动态绑定ComboBox下拉列表: 1. 在您的WinForm添加一个ComboBox控件。 2. 在您的代码,使用ADO.NET连接到您的数据库。 3. 编写一个SQL查询语句来检索您需要添加到ComboBox下拉列表的数据。 4. 使用DataAdapter和DataSet对象来执行查询并将结果保存在一个DataTable对象。 5. 使用ComboBox控件的DataSource属性将DataTable对象与ComboBox控件绑定。 6. 使用ComboBox控件的DisplayMember属性将您希望显示ComboBox下拉列表的数据列的名称指定为字符串。 7. 使用ComboBox控件的ValueMember属性将您希望在选择ComboBox下拉列表的项目返回的值的数据列的名称指定为字符串。 以下是一个示例代码,可以将ComboBox下拉列表动态绑定到数据库的数据: ```csharp using System.Data.SqlClient; // 创建数据库连接 SqlConnection connection = new SqlConnection("Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;"); // 创建SQL查询语句 string query = "SELECT ID, Name FROM MyTable"; // 创建DataAdapter和DataSet对象 SqlDataAdapter adapter = new SqlDataAdapter(query, connection); DataSet dataSet = new DataSet(); // 执行查询并将结果保存在DataTable对象 adapter.Fill(dataSet, "MyTable"); // 将DataTable对象与ComboBox控件绑定 comboBox1.DataSource = dataSet.Tables["MyTable"]; // 指定ComboBox控件显示的数据列的名称 comboBox1.DisplayMember = "Name"; // 指定在选择ComboBox下拉列表的项目返回的值的数据列的名称 comboBox1.ValueMember = "ID"; ``` 当您运行此代码ComboBox下拉列表将显示从数据库检索到的所有项目的名称,并且选择任何项目ComboBox控件将返回该项目的ID作为值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值