C# 添加过滤器到组合框下拉列表

问题描述 投票:0回答:3

需要一些帮助将过滤器添加到我的

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
,因为它在打开的下拉列表中未按预期工作。它正在现有列表之上打开附加列表,但我只能从其下方的下拉列表中进行选择。请参阅下面的打印屏幕:

顶部的列表处于非活动状态,我无法选择文本,但也没有提供显示子字符串的选项。

即使是盒子本身也只有一个

private void SelectJobDropdown_SelectedIndexChanged(object sender, EventArgs e) 
{
    //Plenty of code here 
}

有人可以指出正确的方向,当我在框中输入时如何过滤列表。

请注意,我使用 C# 仅 3 周,因此可能会对这种语言的某些术语或其他方面等感到困惑。

c# winforms filter combobox dropdownbox
3个回答
13
投票

我建议使用 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;            
}

瞧,自动过滤,随后有漂亮的显示和箭头选择。

编辑2

对于不区分大小写的搜索,您可以使用此:

List<string> filteredItems = arrProjectList.FindAll(x => x.ToLower().Contains(filter_param.ToLower()));

注意:

打开下拉列表后,光标将消失。为了防止这种情况,必须将

Cursor.Current
设置为
Cursor.Defualt

comboBox1.DroppedDown = true;
Cursor.Current = Cursors.Default;

1
投票

如果您使用字典作为数据源,以下内容可能很有用。 我在表单中创建了一个静态函数,以便能够重用它,因为我有几个 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; 
}

0
投票

我添加了 keyPress 事件,它对我来说工作正常。它只是关闭原来的下拉列表。

private void combobox_KeyPress(object sender, KeyPressEventArgs e)
{
    combobox.DroppedDown = false;
}
© www.soinside.com 2019 - 2024. All rights reserved.