【发布时间】:2011-05-17 21:54:31
【问题描述】:
如何创建基于字符串过滤文本的自动完成组合框或文本框?
例如:如果我在 TextBox 中键入“a”,我只能看到所有包含“a”的字符串。
【问题讨论】:
-
网络表单?窗体? MVC? WPF?
-
您使用的是哪个版本的框架?您可以访问 LINQ 吗?
标签: c# winforms autocomplete
如何创建基于字符串过滤文本的自动完成组合框或文本框?
例如:如果我在 TextBox 中键入“a”,我只能看到所有包含“a”的字符串。
【问题讨论】:
标签: c# winforms autocomplete
如果您的意思是显示建议,那么当您在所选 IDE 中选择了 TextBox 时,更改属性很简单:
图片中显示的选项允许您更改文本框中自动完成文本的规则以及建议的来源。 (Visual Studio 2010)
您可以前往以下链接了解更多有关 TextBox 控件的信息。
【讨论】:
Windows 窗体的自动完成实现使用 Shell 的自动完成对象,在 Windows Vista 之前只能进行“BeginWith”匹配。 如果您可以要求您的用户升级到 Windows Vista,您可以use IAutoComplete2::SetOptions 指定 ACO_NOPREFIXFILTERING。否则恐怕你需要write your own。
【讨论】:
这是我如何自动完成组合下拉框中的特定值。
void comboBox_Leave(object sender, EventArgs e)
{
ComboBox cbo = (sender as ComboBox);
if (cbo.Text.Length > 0)
{
Int32 rowIndex = cbo.FindString(cbo.Text.Trim());
if (rowIndex != -1)
{
cbo.SelectedIndex = rowIndex;
}
else
{
cbo.SelectedIndex = -1;
}
}
else
{
cbo.SelectedIndex = -1;
}
}
【讨论】:
这会根据用户输入过滤结果。针对大型列表进行优化,填充您自己的数据和错误处理留待您完成:
public partial class Form1 : Form
{
List<String> data;
ListView lst = new ListView();
TextBox txt = new TextBox();
public Form1()
{
InitializeComponent();
data = new List<string>("Lorem ipsum dolor sit amet consectetur adipiscing elit Suspendisse vel".Split());
}
private void Form1_Load(object sender, EventArgs e)
{
this.Controls.Add(txt);
lst.Top = 20;
txt.TextChanged += new EventHandler(txt_TextChanged);
lst.View = View.List;
this.Controls.Add(lst);
list_items("");
}
void txt_TextChanged(object sender, EventArgs e)
{
list_items(txt.Text);
}
void list_items(string filter)
{
lst.Items.Clear();
List<string> results = (from d in data where d.Contains(filter) select d).ToList();
foreach (string s in results)
{
lst.Items.Add(s);
}
}
}
要让组合框自动完成,请设置 AutoCompleteSource 和 AutoCompleteMode 属性:
cbo.AutoCompleteSource = AutoCompleteSource.ListItems;
cbo.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
ListItems 源告诉组合使用它的项目集合作为自动完成源。
【讨论】:
我知道这是一个老话题,但我也非常努力地寻找 C# 自动完成过滤的解决方案,但找不到任何解决方案,所以我想出了自己的简单方法,所以我将分享给那些人谁可能认为它有用并想在他们的项目中使用。它不使用控件的自动完成功能。它所做的只是简单地获取从组合框输入的文本,在源中搜索它,然后仅将源中匹配的文本显示为组合框的新源。我在组合框的KeyUp 事件中实现了它。
假设(实际上,当我想要自动完成时,几乎所有情况下我都会这样做)我们有一个全局分配的 DataTable,称为 dt_source 作为组合框的源,它有两列:id(int) 和 name (字符串)。
DataTable dt_source = new DataTable("table");
dt_source.Columns.Add("id", typeof(int));
dt_source.Columns.Add("name", typeof(string));
这就是我的 KeyUp 方法的样子:
private void cmb_box_KeyUp(object sender, KeyEventArgs e)
{
string srch = cmb_box.Text;
string srch_str = "ABackCDeleteEFGHIJKLMNOPQRSpaceTUVWXYZD1D2D3D4D5D6D7D8D9D0";
if (srch_str.IndexOf(e.KeyCode.ToString()) >= 0)
{
cmb_box.DisplayMember = "name"; // we want name list in the datatable to be shown
cmb_box.ValueMember = "id"; // we want id field in the datatable to be the value
DataView dv_source = new DataView(dt_source); // make a DataView from DataTable so ...
dv_source.RowFilter = "name LIKE '%"+ srch +"%'"; // ... we can filter it
cmb_box.DataSource = dv_source; // append this DataView as a new source to the combobox
/* The 3 lines below is the tricky part. If you repopulate a combobox, the first
item in it will be automatically selected so let's unselect it*/
cmb_box.SelectedIndex = -1; // unselection
/* Again when a combobox repopulated the text region will be reset but we have the
srch variable to rewrite what's written before */
cmb_box.Text = srch;
/* And since we're rewriting the text region let's make the cursor appear at the
end of the text - assuming 100 chars is enough*/
cmb_box.Select(100,0);
cmb_box.DroppedDown = true; // Showing the dropdownlist
}
}
【讨论】:
我认为您最好的选择是覆盖 OnKeyDown(KeyEventArgs e) 事件,并使用该值过滤 ComboBox.AutoCompleteCustomSource。然后如上所述,将 AutoCompleteSource 更改为 AutoCompleteSource.ListItems。
【讨论】:
OnKeyDown 通常被认为是最糟糕的选择。除其他外,它将无法处理粘贴到编辑控件中的输入(例如右键单击 -> 粘贴)。