本文转载于 http://zhidao.baidu.com/question/180144652.html
C# Winform ComboBox 在输入内容时 会在下拉菜单中显示 根据输入内容查询的结果
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