C# 添加过滤器到组合框下拉列表
C# Adding Filter to combobox dropdown list
需要一些帮助来向我的 ComboBox
下拉列表添加过滤器(windows Forms Visual studio 2015)
下拉列表如下所示:
public ReconciliationReport()
{
InitializeComponent();
AppDomain.CurrentDomain.AssemblyResolve += FindDLL;
this.sRootDirectory = Properties.Resources.sRootDirectory;
string[] arrProjectList = Directory.GetDirectories(sRootDirectory).Select(Directory => Path.GetFileName(Directory)).ToArray();
Array.Sort(arrProjectList);
int iProjectCount = arrProjectList.Length;
this.DropDownListSize = iProjectCount;
for (int i = 0; i < iProjectCount; i++)
{
SelectJobDropdown.Items.Add(arrProjectList[i]);
}
}
这为我提供了一个包含所有当前目录的下拉列表。
现在,我需要添加一个文件管理器以仅显示包含输入到 ComboBox
本身的文本的项目,而不管下拉列表本身是否打开。
我已禁用 AutoCompleteMode
和 AutoCompleteSource
,因为它在打开的下拉列表中没有按预期工作。它在现有列表的顶部打开了附加列表,但我只能从其下方的下拉列表中选择 select。请参见下面的打印屏幕:
顶部的列表处于非活动状态,我无法 select 文本,但也没有提供显示子字符串的选项。
即使是盒子本身也只有一个
private void SelectJobDropdown_SelectedIndexChanged(object sender, EventArgs e)
{
//Plenty of code here
}
有人能指出正确的方向吗,当我在框内键入内容时如何过滤列表。
请注意,我使用 C# 仅 3 周,因此可能会对这种语言的某些术语或其他方面等感到困惑。
我建议使用 2 个列表。 1 为原始值
List<string> arrProjectList;
public ReconciliationReport()
{
InitializeComponent();
AppDomain.CurrentDomain.AssemblyResolve += FindDLL;
this.sRootDirectory = Properties.Resources.sRootDirectory;
arrProjectList = Directory.GetDirectories(sRootDirectory).Select(Directory => Path.GetFileName(Directory)).ToList();
arrProjectList.Sort();
// then just bind it to the DataSource of the ComboBox
SelectJobDropdown.DataSource = arrProjectList;
// don't select automatically the first item
SelectJobDropdown.SelectedIndex = -1;
}
和 1 表示过滤后的值。在此示例中,我使用 TextBox
来捕获过滤器文本。在 TextChanged
事件中,获取过滤文本并仅从原始 arrProjectList
列表中提取那些值。如果过滤器为空,您将需要在末尾添加一个额外选项以将绑定重置为旧列表。
private void textBox1_TextChanged(object sender, EventArgs e)
{
string filter_param = textBox1.Text;
List<string> filteredItems = arrProjectList.FindAll(x => x.Contains(filter_param));
// another variant for filtering using StartsWith:
// List<string> filteredItems = arrProjectList.FindAll(x => x.StartsWith(filter_param));
comboBox1.DataSource = filteredItems;
// if all values removed, bind the original full list again
if (String.IsNullOrWhiteSpace(textBox1.Text))
{
comboBox1.DataSource = arrProjectList;
}
// this line will make sure, that the ComboBox opens itself to show the filtered results
}
编辑
我找到了直接将过滤器输入 ComboBox
的解决方案。过滤过程相同,但使用 TextUpdate
事件需要取消选择绑定后自动设置为第一个元素的 SelectedIndex
。然后我猜你想继续写你的过滤器(不止一个字母),把过滤器写回 ComboBox.Text
属性 并将光标位置设置到末尾:
private void comboBox1_TextUpdate(object sender, EventArgs e)
{
string filter_param = comboBox1.Text;
List<string> filteredItems = arrProjectList.FindAll(x => x.Contains(filter_param));
// another variant for filtering using StartsWith:
// List<string> filteredItems = arrProjectList.FindAll(x => x.StartsWith(filter_param));
comboBox1.DataSource = filteredItems;
if (String.IsNullOrWhiteSpace(filter_param))
{
comboBox1.DataSource = arrProjectList;
}
comboBox1.DroppedDown = true;
// this will ensure that the drop down is as long as the list
comboBox1.IntegralHeight = true;
// remove automatically selected first item
comboBox1.SelectedIndex = -1;
comboBox1.Text = filter_param;
// set the position of the cursor
comboBox1.SelectionStart = filter_param.Length;
comboBox1.SelectionLength = 0;
}
Et voilà automatic filtering with a nice display and arrow selection after.
编辑 2
对于不区分大小写的搜索,您可以使用这个:
List<string> filteredItems = arrProjectList.FindAll(x => x.ToLower().Contains(filter_param.ToLower()));
注意:
下拉列表打开后cursor will disappear。为了防止这种情况,必须将 Cursor.Current
设置为 Cursor.Defualt
comboBox1.DroppedDown = true;
Cursor.Current = Cursors.Default;
如果您使用字典作为数据源,以下内容可能会有用。
我在表单中创建了一个静态函数以便能够重用它,因为我有多个 ComboBox 实例,我希望它们具有相同的行为。
只需从传递控件名称和源字典的 TextUpdate 事件中调用该函数。
private static void FilterComboBox(ComboBox combo, Dictionary<int, string> dataSource)
{
var filter = combo.Text;
if (string.IsNullOrWhiteSpace(filter))
return;
var filteredItems = dataSource.Where(kv => kv.Value.Contains(filter)).ToDictionary(k => k.Key, k => k.Value);
combo.DisplayMember = "Value";
combo.ValueMember = "Key";
combo.DataSource = new BindingSource(filteredItems, null);
// this will ensure that the drop down is as long as the list
combo.IntegralHeight = false;
combo.IntegralHeight = true;
combo.DroppedDown = true;
// remove automatically selected first item
combo.SelectedIndex = -1;
combo.Text = filter;
// set the position of the cursor
combo.SelectionStart = filter.Length;
combo.SelectionLength = 0;
}
需要一些帮助来向我的 ComboBox
下拉列表添加过滤器(windows Forms Visual studio 2015)
下拉列表如下所示:
public ReconciliationReport()
{
InitializeComponent();
AppDomain.CurrentDomain.AssemblyResolve += FindDLL;
this.sRootDirectory = Properties.Resources.sRootDirectory;
string[] arrProjectList = Directory.GetDirectories(sRootDirectory).Select(Directory => Path.GetFileName(Directory)).ToArray();
Array.Sort(arrProjectList);
int iProjectCount = arrProjectList.Length;
this.DropDownListSize = iProjectCount;
for (int i = 0; i < iProjectCount; i++)
{
SelectJobDropdown.Items.Add(arrProjectList[i]);
}
}
这为我提供了一个包含所有当前目录的下拉列表。
现在,我需要添加一个文件管理器以仅显示包含输入到 ComboBox
本身的文本的项目,而不管下拉列表本身是否打开。
我已禁用 AutoCompleteMode
和 AutoCompleteSource
,因为它在打开的下拉列表中没有按预期工作。它在现有列表的顶部打开了附加列表,但我只能从其下方的下拉列表中选择 select。请参见下面的打印屏幕:
顶部的列表处于非活动状态,我无法 select 文本,但也没有提供显示子字符串的选项。
即使是盒子本身也只有一个
private void SelectJobDropdown_SelectedIndexChanged(object sender, EventArgs e)
{
//Plenty of code here
}
有人能指出正确的方向吗,当我在框内键入内容时如何过滤列表。
请注意,我使用 C# 仅 3 周,因此可能会对这种语言的某些术语或其他方面等感到困惑。
我建议使用 2 个列表。 1 为原始值
List<string> arrProjectList;
public ReconciliationReport()
{
InitializeComponent();
AppDomain.CurrentDomain.AssemblyResolve += FindDLL;
this.sRootDirectory = Properties.Resources.sRootDirectory;
arrProjectList = Directory.GetDirectories(sRootDirectory).Select(Directory => Path.GetFileName(Directory)).ToList();
arrProjectList.Sort();
// then just bind it to the DataSource of the ComboBox
SelectJobDropdown.DataSource = arrProjectList;
// don't select automatically the first item
SelectJobDropdown.SelectedIndex = -1;
}
和 1 表示过滤后的值。在此示例中,我使用 TextBox
来捕获过滤器文本。在 TextChanged
事件中,获取过滤文本并仅从原始 arrProjectList
列表中提取那些值。如果过滤器为空,您将需要在末尾添加一个额外选项以将绑定重置为旧列表。
private void textBox1_TextChanged(object sender, EventArgs e)
{
string filter_param = textBox1.Text;
List<string> filteredItems = arrProjectList.FindAll(x => x.Contains(filter_param));
// another variant for filtering using StartsWith:
// List<string> filteredItems = arrProjectList.FindAll(x => x.StartsWith(filter_param));
comboBox1.DataSource = filteredItems;
// if all values removed, bind the original full list again
if (String.IsNullOrWhiteSpace(textBox1.Text))
{
comboBox1.DataSource = arrProjectList;
}
// this line will make sure, that the ComboBox opens itself to show the filtered results
}
编辑
我找到了直接将过滤器输入 ComboBox
的解决方案。过滤过程相同,但使用 TextUpdate
事件需要取消选择绑定后自动设置为第一个元素的 SelectedIndex
。然后我猜你想继续写你的过滤器(不止一个字母),把过滤器写回 ComboBox.Text
属性 并将光标位置设置到末尾:
private void comboBox1_TextUpdate(object sender, EventArgs e)
{
string filter_param = comboBox1.Text;
List<string> filteredItems = arrProjectList.FindAll(x => x.Contains(filter_param));
// another variant for filtering using StartsWith:
// List<string> filteredItems = arrProjectList.FindAll(x => x.StartsWith(filter_param));
comboBox1.DataSource = filteredItems;
if (String.IsNullOrWhiteSpace(filter_param))
{
comboBox1.DataSource = arrProjectList;
}
comboBox1.DroppedDown = true;
// this will ensure that the drop down is as long as the list
comboBox1.IntegralHeight = true;
// remove automatically selected first item
comboBox1.SelectedIndex = -1;
comboBox1.Text = filter_param;
// set the position of the cursor
comboBox1.SelectionStart = filter_param.Length;
comboBox1.SelectionLength = 0;
}
Et voilà automatic filtering with a nice display and arrow selection after.
编辑 2
对于不区分大小写的搜索,您可以使用这个:
List<string> filteredItems = arrProjectList.FindAll(x => x.ToLower().Contains(filter_param.ToLower()));
注意:
下拉列表打开后cursor will disappear。为了防止这种情况,必须将 Cursor.Current
设置为 Cursor.Defualt
comboBox1.DroppedDown = true;
Cursor.Current = Cursors.Default;
如果您使用字典作为数据源,以下内容可能会有用。 我在表单中创建了一个静态函数以便能够重用它,因为我有多个 ComboBox 实例,我希望它们具有相同的行为。 只需从传递控件名称和源字典的 TextUpdate 事件中调用该函数。
private static void FilterComboBox(ComboBox combo, Dictionary<int, string> dataSource)
{
var filter = combo.Text;
if (string.IsNullOrWhiteSpace(filter))
return;
var filteredItems = dataSource.Where(kv => kv.Value.Contains(filter)).ToDictionary(k => k.Key, k => k.Value);
combo.DisplayMember = "Value";
combo.ValueMember = "Key";
combo.DataSource = new BindingSource(filteredItems, null);
// this will ensure that the drop down is as long as the list
combo.IntegralHeight = false;
combo.IntegralHeight = true;
combo.DroppedDown = true;
// remove automatically selected first item
combo.SelectedIndex = -1;
combo.Text = filter;
// set the position of the cursor
combo.SelectionStart = filter.Length;
combo.SelectionLength = 0;
}