ListBox filter with TextBox in real time

I am trying to filter a list box 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 problems:

  • When I run the program, I get this error: Object reference not set to an instance of an object

  • If I hit backspace, my original list is no longer displayed. This is because my actual list of items is now zoomed out, but how can I achieve this?

Can you point me in the right direction?

+4


source to share


6 answers


It's hard to subtract from the code alone, but I suppose the filtering issue comes from various aspects:

a) You need the Model

data shown on ListBox

. You need a team of "objects" that you keep somewhere ( Dictionary

, DataBase

, XML

, BinaryFile

, Collection

)), something like Store shorter.

To display data in the UI, you always select data from that store, filter it, and put it in the UI.



b) After the first point, your filtering code might look like this (pseudocode)

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 it helps.

+6


source


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());
}

      

0


source


Yes, that was the answer to filtering. (slightly changed). I had the information 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();

      

The error seems to be:

Object reference not set to object instance

is somewhere else in my code, can't push it.

0


source


If possible, keep everything in a dictionary and just fill it out 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();
}
}

      

0


source


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 complete the registration lists the first time you fill out the list.

Hope this helps.

0


source


this was a very difficult problem for me, but I found a workaround (not so easy) that works for me.

on the aspx page:

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

      

I had this two fields. I need an HTML input type because of the "oninput" function, which is not available on classic asp.net controls.

I have defined these two JavaScript functions:

    <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>

      

Now you can use postback in your code to get the value of the hidden field every time any one character is entered into the input field:

    If IsPostBack Then
        FiltraLbox(hf1.Value)
    End If

      

FiltraLbox (hf1.Value) function changes the Listbox data source and binds it:

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

      

Finally, we can call the setTboxValue function, which overwrites the input text value that we lose on postback, and set focus to it.

Hope this works for you.

Enjoy it.

0


source







All Articles