How to implement instant DataGrid'a filter using multi-threading (WPF)?

There is a DataGrid, it is bound ObservableCollection. Filtering DataGrid'a hanging on a TextChanged event from a TextBox'in which the input string to be filtered. Filter by forming a new collection of elements whose names match the filter. All anything, but if you enter a string, which satisfies a lot of elements enter in the TextBox begins to slow down. How to parallelize and implement a truly instant filtering without hanging UI? So every time you change the text, if the previous filter did not work still, then cancel it, clear the collection and re-filtered, and it would not have frozen.

Tried BackgroundWorker, but since, apparently, the filtering function is converted to a collection of changes which change the contents of a DataGrid', nothing works, after cleaning the collection DoWork method just silently fails:

... DoWork(...)
{
collection.Clear(); // clears the collection, but the DataGrid is not cleared
.... // to this line, the execution does not reach
}
September 26th 19 at 11:51
2 answers
September 26th 19 at 11:53
Solution
You don't need to filter to rebuild the collection. To achieve this, wpf has already developed the necessary mechanisms.
First of all you need a collection with which you are working to put in a CollectionView. CollectionView to bind to a DataGrid.
Have a CollectionView which has built-in filtering mechanisms, the result will be displayed in the DataGrid.
Cm. The Filter Property Of The CollectionView.

To use the CollectionView is wrapped in a CollectionViewSource or something like that. This is described in detail in the examples. It can simply describe even in Xaml.
Example example code with dynamic creation of List over a CollectionViewSource and filtered via the TextBox:
Xaml
<window x:class="WpfApplication3.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" title="MainWindow" height="350" width="525"> 
<grid>
<grid.rowdefinitions>
 <rowdefinition height="47*">
 <rowdefinition height="275*">
</rowdefinition></rowdefinition></grid.rowdefinitions>
 <textbox x:name="filter" textchanged="filter_TextChanged">
 <listbox x:name="lst" grid.row="1">
</listbox></textbox></grid>
</window>


C#
public partial class MainWindow : Window
{
 public MainWindow()
{
InitializeComponent();
 List<string> lstSource = new List<string>() { "1", "2","3" };
 viewSource = new CollectionViewSource();
 viewSource.Source = lstSource; 
 viewSource.Filter += viewSource_Filter;
 lst.ItemsSource = viewSource.View;
}

 CollectionViewSource viewSource;
 void viewSource_Filter(object sender, FilterEventArgs e)
{
 e.Accepted = ((string)e.Item).IndexOf(filter.Text) >=0;
}

 private void filter_TextChanged(object sender, TextChangedEventArgs e)
{
viewSource.View.Refresh();
}
}</string></string>
Tried CollectionView, enter a filter string began to slow down even more, nothing is filtered, although the filter predicate correct feed, and in debug it is visible that the method works correctly, but the filtering still all the elements of the original collection. What am I doing wrong? - Irving40 commented on September 26th 19 at 11:56
Whatever brakes you need the filter to run with a delay via timer. If the user manages to press a few keys, the timer is restarted, if the user pause the timer fires and invokes the filter. Latency may be 500 MS - 1 s

In response, added a sample using a CollectionView. - cassie.Schaden commented on September 26th 19 at 11:59
September 26th 19 at 11:55
Apparently, you are wrong cook asynchronous tasks. Maybe this will help.

Find more questions by tags C#