Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multi-threading WPF on the UI

In my C# WPF application I have a DataGrid and right above it there is a TextBox for the user to search and filter the grid as they type. If the user types fast though, no text will appear until 2 seconds after they type because the UI thread is too busy updating the grid.

Since most of the delay is all on the UI side (i.e. filtering the datasource is nearly instant, but rebinding and re-rendering the grid is slow), multi-threading has not been helpful. I then tried setting the dispatcher of just the grid to be at a lower level while the grid gets updated, but this didn't solve the issue either. Here's some code... Any suggestions on how to solve this type of problem?

string strSearchQuery = txtFindCompany.Text.Trim();

this.dgCompanies.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(delegate
    {
        //filter data source, then
        dgCompanies.ItemsSource = oFilteredCompanies;
    }));
like image 666
Nullqwerty Avatar asked Feb 14 '23 13:02

Nullqwerty


1 Answers

Using a ListCollectionView as your ItemsSource for the grid and updating the Filter works much faster than re-assigning the ItemsSource.

The example below filters 100000 rows with no apparent lag by simply refreshing the View in the setter for the search term text property.

ViewModel

class ViewModel
    {
        private List<string> _collection = new List<string>(); 
        private string _searchTerm;

        public ListCollectionView ValuesView { get; set; }

        public string SearchTerm
        {
            get
            {
                return _searchTerm;
            }
            set
            {
                _searchTerm = value;
                ValuesView.Refresh();
            }
        }

        public ViewModel()
        {
            _collection.AddRange(Enumerable.Range(0, 100000).Select(p => Guid.NewGuid().ToString()));

            ValuesView = new ListCollectionView(_collection);
            ValuesView.Filter = o =>
                {
                    var listValue = (string)o;
                    return string.IsNullOrEmpty(_searchTerm) || listValue.Contains(_searchTerm);
                };
        }
    }

View

<TextBox Grid.Row="0" Text="{Binding SearchTerm, UpdateSourceTrigger=PropertyChanged}" />

<ListBox ItemsSource="{Binding ValuesView}"
         Grid.Row="1" />

like image 69
gͫrͣeͬeͨn Avatar answered Feb 16 '23 03:02

gͫrͣeͬeͨn