UI上的多线程WPF

时间:2021-10-21 00:35:33

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.

在我的C#WPF应用程序中,我有一个DataGrid,在它上面有一个TextBox供用户在键入时搜索和过滤网格。如果用户快速键入,则在键入后2秒内不会显示任何文本,因为UI线程太忙于更新网格。

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?

由于大部分延迟都在UI端(即过滤数据源几乎是即时的,但重新绑定和重新渲染网格很慢),多线程并没有帮助。然后我尝试将网格的调度程序设置为较低级别,同时网格更新,但这也没有解决问题。这里有一些代码......关于如何解决这类问题的任何建议?

string strSearchQuery = txtFindCompany.Text.Trim();

this.dgCompanies.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(delegate
    {
        //filter data source, then
        dgCompanies.ItemsSource = oFilteredCompanies;
    }));

2 个解决方案

#1


3  

If you are targeting .net 4.5, an option is to set the Delay property on your TextBox which will prevent setting the source value until a certain time threshold is met (until the user stops typing).

如果您的目标是.net 4.5,则选项是在TextBox上设置Delay属性,这将阻止设置源值,直到满足特定时间阈值(直到用户停止键入)。

<TextBox Text="{Binding SearchText, Delay=1000}"/>

This waits for 1 second after there is no user input to set the source value.

在没有用户输入来设置源值之后等待1秒。

Another option is to have a button trigger your filter/search instead of when the textbox changes.

另一个选项是让按钮触发您的过滤器/搜索,而不是文本框更改时。

#2


5  

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

使用ListCollectionView作为GridS的ItemsSource并更新Filter比重新分配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.

通过简单地刷新搜索词文本属性的setter中的View,下面的示例过滤了100000行,没有明显的延迟。

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" />

#1


3  

If you are targeting .net 4.5, an option is to set the Delay property on your TextBox which will prevent setting the source value until a certain time threshold is met (until the user stops typing).

如果您的目标是.net 4.5,则选项是在TextBox上设置Delay属性,这将阻止设置源值,直到满足特定时间阈值(直到用户停止键入)。

<TextBox Text="{Binding SearchText, Delay=1000}"/>

This waits for 1 second after there is no user input to set the source value.

在没有用户输入来设置源值之后等待1秒。

Another option is to have a button trigger your filter/search instead of when the textbox changes.

另一个选项是让按钮触发您的过滤器/搜索,而不是文本框更改时。

#2


5  

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

使用ListCollectionView作为GridS的ItemsSource并更新Filter比重新分配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.

通过简单地刷新搜索词文本属性的setter中的View,下面的示例过滤了100000行,没有明显的延迟。

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" />