Using the ListCollectionView with a deferred Filter method in WPF with C#

In another blog I covered how to perform filtering using the ListCollectionView class on a datagrid. What I noticed on the implementation on a larger result set was a little lag in the response when characters were being entered into the filter textbox. The way it was implemented was for each character entered; perform a filter on the datagrid.

I started thinking that it would be better to start a filter a few milliseconds after the user stopped entering the filter before performing the filter. I think it is logical that a user would not want to filter on a single character.

The first action I took was to create a DelayAction class.

public class DelayAction : IDisposable
     {
         private Timer timer;
 
         public static DelayAction Initialize(Action action)
         {
             if (action == null)
             {
                 throw new
                 ArgumentNullException
                   ("DeferredAction Initialize NULL excpetion");
             }
 
             return new DelayAction(action);
         }
 
         private DelayAction(Action action)
         {
             this.timer = new Timer(new TimerCallback(delegate
             {
                 Application.Current.Dispatcher.Invoke(action);
             }));
         }
 
         public void Wait(TimeSpan delay)
         {
             this.timer.Change(delay,
                               TimeSpan.FromMilliseconds(-1));
         }
}

In the MainWindow.xaml.cs code-behind I will create an instance of the Delayed class and call the Wait() method. The Wait() method is where I will specific how much time to wait before executing the method I want to delay. In this example it is the method which filters the datagrid based on user input.

private readonly TimeSpan filterDelay =  TimeSpan.FromMilliseconds(500);
private DelayAction delayedAction;

In the above code I also create a TimeSpan instance and set it to 500 milliseconds. I will use the filterDelay as the parameter for the Wait() method.

The DelayAction class is implemented in the textbox TextChanged event. Instead of calling the FilterIt() method immediately after each TextChanged event, it will wait for the amount of time which is passed to the Wait() method.

if (delayedAction == null)
{
     delayedAction = DelayAction.Initialize(() => FilterIt());
}
delayedAction.Wait(filterDelay);

I think if you are going to implement a filtering capability then you should implement this delay too. The response if better and the user will be more satisfied. However, you need to recognize that this method only filters what have been loaded into the local datagrid. If you need to implement a FULL-TEXT search of the database, that is a whole other story. Both Oracle and Microsoft SQL Server have solutions for this. My other articles covering Lucene.Net can provide a solution for this too.

Download the source