K
K
kodwi2014-07-25 00:04:48
C++ / C#
kodwi, 2014-07-25 00:04:48

How to implement instant datagrid filtering using multithreading (WPF)?

I have a DataGrid with an ObservableCollection attached to it. The DataGrid's filtering function hangs on the TextChanged event of the TextBox, in which we enter a string to filter. I filter by forming a new collection of elements whose names match the filter. Everything would be fine, but when you enter a string that many elements satisfy, the input in the TextBox starts to slow down. How can you parallelize and implement really instantaneous filtering without freezing the UI? So that every time the text changes, if the previous filter has not worked yet, then we cancel it, clear the collection and filter again, and nothing would hang.
I tried the BackgroundWorker, but since, apparently, the collection is converted into the filtering function, the changes of which also change the contents of the DataGrid, nothing works, after clearing the collection, the DoWork method simply ends silently:

... DoWork(...)
{
collection.Clear(); // очищает коллекцию, но DataGrid не очищается
.... // до этой строчки выполнение вообще не доходит
}

Answer the question

In order to leave comments, you need to log in

2 answer(s)
S
Sumor, 2014-07-25
@kodwi

You don't need to rebuild the collection for filtering. For this, the necessary mechanisms have already been developed in wpf.
First of all, you need to place the collection you are working with in the CollectionView. CollectionView bind to DataGrid.
CollectionView has built-in filtering mechanisms - the result will be displayed in the DataGrid.
See Filter CollectionView property .
For use, the CollectionView is wrapped in a CollectionViewSource or something similar. This is described in detail in the examples. It can be simply described even in Xaml.
Sample code with dynamically creating a CollectionViewSource over a List and filtering through a 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*"/>
        </Grid.RowDefinitions>
        <TextBox x:Name="filter" TextChanged="filter_TextChanged"/>
        <ListBox x:Name="lst" Grid.Row="1" />
    </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();
    }
}

D
Deerenaros, 2014-07-25
@Deerenaros

Apparently, you are preparing asynchronous tasks incorrectly . Perhaps this will help.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question