C# 使用 TextBox 实时过滤 ListBox

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9983720/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 12:00:18  来源:igfitidea点击:

Filter ListBox with TextBox in realtime

c#winformslisttextboxlistbox

提问by observ

I am trying to filter an listbox with text from a textbox, realTime.

我正在尝试从文本框中实时过滤带有文本的列表框。

Here is the code:

这是代码:

private void SrchBox_TextChanged_1(object sender, EventArgs e)
{
  var registrationsList = registrationListBox.Items.Cast<String>().ToList();
  registrationListBox.BeginUpdate();
  registrationListBox.Items.Clear();
  foreach (string str in registrationsList)
  {
    if (str.Contains(SrchBox.Text))
    {
      registrationListBox.Items.Add(str);
    }
  }
  registrationListBox.EndUpdate();
}

Here are the issues:

以下是问题:

  1. When I run the program i get this error: Object reference not set to an instance of an object

  2. If I hit backspace, my initial list is not shown anymore. This is because my actual list of items is now reduced, but how can I achieve this?

  1. 当我运行程序时,我收到此错误: Object reference not set to an instance of an object

  2. 如果我按退格键,则不再显示我的初始列表。这是因为我的实际项目清单现在减少了,但我怎样才能做到这一点?

Can you point me in the right direction?

你能为我指出正确的方向吗?

采纳答案by Tigran

It's hard to deduct just from the code, but I presumeyour filtering problem born from the different aspects:

仅从代码中很难推断出,但我认为您的过滤问题来自不同方面:

a) You need a Modelof the data shown on ListBox. You need a colleciton of "Items" which you hold somewhere (Dictionary, DataBase, XML, BinaryFile, Collection), some kind of Storein short.

a) 您需要Model中显示的数据ListBox。您需要在某处 ( Dictionary, DataBase, XML, BinaryFile, Collection)保存的“物品”集合,简称为某种Store

To show the data on UI you alwayspick the data from that Store, filter it and put it on UI.

要在 UI 上显示数据,您总是从该Store 中选择数据,对其进行过滤并将其放在 UI 上。

b) After the first point your filtering code can look like this (a pseudocode)

b) 在第一点之后,您的过滤代码可能如下所示(伪代码

var registrationsList = DataStore.ToList(); //return original data from Store

registrationListBox.BeginUpdate();
registrationListBox.Items.Clear();

if(!string.IsNullOrEmpty(SrchBox.Text)) 
{
  foreach (string str in registrationsList)
  {                
     if (str.Contains(SrchBox.Text))
     {
         registrationListBox.Items.Add(str);
     }
  }
}
else 
   registrationListBox.Items.AddRange(registrationsList); //there is no any filter string, so add all data we have in Store

registrationListBox.EndUpdate();

Hope this helps.

希望这可以帮助。

回答by James Johnson

Something like this might work for you:

像这样的事情可能对你有用:

var itemList = registrationListBox.Items.Cast<string>().ToList();
if (itemList.Count > 0)
{
    //clear the items from the list
    registrationListBox.Items.Clear();

    //filter the items and add them to the list
    registrationListBox.Items.AddRange(
        itemList.Where(i => i.Contains(SrchBox.Text)).ToArray());
}

回答by observ

Yes that was the answer to filtering. (modified a bit). I had the info in a text file. This is what worked for me

是的,这就是过滤的答案。(稍作修改)。我有一个文本文件中的信息。这对我有用

FileInfo registrationsText = new FileInfo(@"name_temp.txt");
            StreamReader registrationsSR = registrationsText.OpenText();
            var registrationsList = registrationListBox.Items.Cast<string>().ToList();

            registrationListBox.BeginUpdate();
            registrationListBox.Items.Clear();

            if (!string.IsNullOrEmpty(SrchBox.Text))
            {
                foreach (string str in registrationsList)
                {
                    if (str.Contains(SrchBox.Text))
                    {
                        registrationListBox.Items.Add(str);
                    }
                }
            }
            else
                while (!registrationsSR.EndOfStream)
                {
                    registrationListBox.Items.Add(registrationsSR.ReadLine());
                }
            registrationListBox.EndUpdate();

It seems that the error:

似乎是错误:

Object reference not set to an instance of an object

你调用的对象是空的

is from somewhere else in my code, can't put my finger on it.

来自我代码中的其他地方,我无法理解它。

回答by KC Drez

If able, store everything in a dictionary and just populate it from there.

如果可以,将所有内容存储在字典中,然后从那里填充它。

public partial class myForm : Form
{
    private Dictionary<string, string> myDictionary = new Dictionary<string, string>();
//constructor. populates the items. Assumes there is a listbox (myListbox) and a textbox (myTextbox), named respectively
public myForm()
{
    InitializeComponent();
    myDictionary.Add("key1", "item1");
    myDictionary.Add("key2", "My Item");
    myDictionary.Add("key3", "A Thing");

    //populate the listbox with everything in the dictionary
    foreach (string s in myDictionary.Values)
        myListbox.Add(s);
}
//make sure to connect this to the textbox change event
private void myTextBox_TextChanged(object sender, EventArgs e)
{
    myListbox.BeginUpdate();
    myListbox.Items.Clear();
    foreach (string s in myDictionary.Values)
    {
        if (s.Contains(myListbox.Text))
            myListbox.Items.Add(s);
    }
    myListbox.EndUpdate();
}
}

回答by Anonimous

I would do it like this:

我会这样做:

private List<string> registrationsList;

private void SrchBox_TextChanged_1(object sender, EventArgs e)
{
  registrationListBox.BeginUpdate();
  registrationListBox.Items.Clear();

  var filteredList = registrationList.Where(rl => rl.Contains(SrchBox.Text))

  registrationListBox.Items.AddRange();

  registrationListBox.EndUpdate();
}

Just remember to populate registrationsList the first time you fill your listbox.

请记住在您第一次填充列表框时填充注册列表。

Hope this helps.

希望这可以帮助。

回答by Giorgio C.

it was a very hard issue for me, but I found a workaround (not so simple) that works fine for me.

这对我来说是一个非常困难的问题,但我找到了一个对我来说很好的解决方法(不是那么简单)。

on aspx page:

在aspx页面上:

<input id="ss" type="text" oninput="writeFilterValue()"/>
<asp:HiddenField ID="hf1" runat="server" Value="" ClientIDMode="Static" />

I need HTML input type because of "oninput" function, that is not availiable on classic asp.net controls. The writeFilterValue() function causes a postback that filters values of a given ListBox (in code-behind).

由于“oninput”功能,我需要 HTML 输入类型,这在经典的 asp.net 控件上不可用。writeFilterValue() 函数导致过滤给定 ListBox(在代码隐藏中)的值的回发。

I've defined this two javascript function:

我已经定义了这两个 javascript 函数:

    <script type="text/javascript">

    function writeFilterValue() {
        var bla = document.getElementById("ss").value;
        $("#hf1").val(bla)
        __doPostBack();
    }

    function setTboxValue(s) {
        document.getElementById('ss').value = s;
        document.getElementById('ss').focus();
    }

</script>

You can now use postback on code-behind to capture hf1 value, every time some single Character is typed on inputbox. On code-behind:

您现在可以在代码隐藏上使用回发来捕获 hf1 值,每次在输入框上键入单个字符时。关于代码隐藏:

    If IsPostBack Then
        FiltraLbox(hf1.Value)
    End If

The function FiltraLbox(hf1.Value) changes datasource of Listbox, and rebind it:

函数 FiltraLbox(hf1.Value) 改变 Listbox 的数据源,并重新绑定它:

Public Sub FiltraLbox(ByVal hf As String)

    If hf <> "" Then


    ' change datasource here, that depends on hf value,


        ListBox1.DataBind()

        ScriptManager.RegisterStartupScript(Page, Page.GetType(), "text", setTboxValue('" + hf + "');", True)
    End If

End Sub

At the end I call the function setTboxValue(), that rewrites the input text value lost on postback, and puts the focus on it.

最后,我调用函数 setTboxValue(),它重写回发时丢失的输入文本值,并将重点放在它上面。

Enjoy it.

好好享受。