views:

153

answers:

5

Hey guys,

I'm writing a filter that will pick out items. I have a list of Objects. The objects contain a number, name and some other irrelevant items. At the moment, the list contains 200 items. When typing in a textbox, i'm looking if the string matches a part of the number/name of the objects in the list. If so, add them to the listbox. Here's the code for my textbox textchanged event :

private void txtTelnumber_TextChanged(object sender, TextChangedEventArgs e)
    {
        lstOverview.Items.Clear();
        string data = "";
        foreach (ucTelListItem telList in _allUsers)
        {
            data = telList.User.H323 + telList.user.E164;
            if (data.Contains(txtTelnumber.Text))
                lstOverview.Items.Add(telList);
        }
    }

I sometimes see a little delay when entering a character, especially when i go from 4 records to 200 records (so when i had a filter and 4 records matched, and i backspace and the whole list appears again). My list is a list of usercontrols, cause i found it takes less time to load the usercontrols from a list, then to have to initialize a new usercontrol each time.

Can i do something about the code, or is it just adding the usercontrol the listbox that causes the small delay (small delay = <1 sec)?

Thanks in advance.

Edit I've edited post, it's wpf. And putting items in a list and setting the itemssource isn't solving the problem.

A: 

Wrap your code with BeingUpdate/EndUpdate to stop redrawing when adding the items.

private void txtTelnumber_TextChanged(object sender, TextChangedEventArgs e)
{
    lstOverview.BeginUpdate();
    lstOverview.Items.Clear();
    string data = "";
    foreach (ucTelListItem telList in _allUsers)
    {
        data = telList.User.H323 + telList.user.E164;
        if (data.Contains(txtTelnumber.Text))
            lstOverview.Items.Add(telList);
    }
    lstOverview.EndUpdate();
}
jgauffin
ok, i thought i had it. my app is in wpf, this method is winforms, so i started looking for an equivalent, but nothing seems to be the same. Still experiencing the same problem though.
djerry
+1  A: 

I'd suggest you two techniques to be used in concert:

  1. Before clearing and adding item to the ListBox invoke the BeginUpdate() method, and invoke its EndUpdate() when you finish adding items. These methods are specifically there for avoiding performance loss during a massive insertion of items.
  2. Introduce a timer and make the filtering task start only after a specific amount of time has been elapsed after the last KeyUp event of the TextBox. In this way you augment the chance of not evaluating a filter that is not yet significant to the user.
Erik Burigo
option 2 is a no go (good suggesting though), but it needs to show immediatly. I'll try the first one.
djerry
You're welcome. Actually they are applicable independently. With "specific amount of time" I mean something like a 1-second span or less (a bit more of the time a person leaves between two consecutive keystrokes).
Erik Burigo
True, and as BeginUpdate and EndUpdate won't work in my wpf app, i think this will be the only solution, but i'll have to convince my client then. :)
djerry
Oh! I see... I'm far from being a WPF expert. Peeking on MSDN I've found that the *memeber footprint* of the control is quite different :) However there are methods and properties (BeginInit(), EndInit() or CacheMode) that would be my first try. I'm not confident enough to post them as an answer, however.
Erik Burigo
hm, for the moment, the timer will have to do. the problem is not solved, but this gives a reasonable solution
djerry
A: 
private void txtTelnumber_TextChanged(object sender, TextChangedEventArgs e)
{ 
    lstOverview.DataSource=_allUsers.FindAll(delegate(ObjType telList)
    {
        return (telList.User.H323.Contains(txtTelnumber.Text) || telList.user.E164.Contains(txtTelnumber.Text) );
    });
}

try the above code

Space Cracker
where does ObjType come from? And Datasource can't be applied to my listbox.
djerry
it's a method parameter but it's appear as it's anonymous method using delegates .. you can take from delegate keyword tell } and make it as a separate method and call it in FindAlli wish that's help you
Space Cracker
A: 

You have only 200 items??? You should not be experiencing any lag in performance then in WPF. Just populate your data into an ObservableCollection and inturn bind it to the listview. Now in your textchanged event you can apply the same filter logic but to the ObservableCollection instead of the listview. The listview should reflect the changes instantly.

I'm working with millions of records without any lag.

You never want to create delays

Also take a look at VirtualMode property for advanced operations.

Update

And it seems you're doing this operation data = telList.User.H323 + telList.user.E164; in every textchanged event. You can better create a List<data> beforehand and implement only your filter logic inside the loop.

Veer
i've tried with this option, but another problem occurs. When i type "ere", then i need to show all items which contain "ere". But when i backspace or delete, i need to refill the collection again. so if delete directly from the ObservableCollection, i lose items i might need to add later again.Or i need 2 collections, one with all items, and one binded, and then i have to put in a control method to check wether the binded collection already contains an element... see my problem?
djerry
Yes, it is a must that you need to use 2 collection and you're currently using it. one is _allUsers and the other is your listviewcollection. What i told you is to replace your listviewcollection to observablecollection, your maincollection being the same. In the long run you can also have list of ObservableCollections which will act as a history when the backspace is pressed.
Veer
+1  A: 

I have just figured out what caused the delay on loading items into my listbox. I'm using predefined themes (Wpf Themes) and because my listbox is all pimped, it takes longer to be redrawn. So it's nothing to do with programming logic, just the style is delaying my filter.

djerry
Good. Still you can opt for binding rather.
Veer