多线程在WPF上的UI界面实现

4
在我的C# WPF应用程序中,我有一个DataGrid,并且在它的正上方有一个TextBox供用户搜索和过滤表格。如果用户输入速度很快,那么在他们键入后2秒钟内不会出现任何文本,因为UI线程太忙于更新表格。
由于大部分延迟都在UI端(即过滤数据源几乎是瞬间完成的,但重新绑定和重新渲染表格很慢),多线程并没有帮助。然后我尝试将仅表格的调度程序设置为较低级别,同时更新表格,但这也没有解决问题。以下是一些代码...有没有解决这种问题的建议?
string strSearchQuery = txtFindCompany.Text.Trim();

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

2
发布您当前的XAML。很可能是因为您正在破坏UI虚拟化,这就是为什么UI“缓慢”的原因。而且您应该使用CollectionView来解决此问题。 - Federico Berasategui
是的。就像:有快速网格。用户界面是单线程的,但2秒钟很长 - 应该研究一下这个问题。不要试图绕过真正的问题,即开始时的2秒更新。 - TomTom
这不是虚拟化。我知道因为我可以关闭它,然后会经历更长的加载时间。这只需要1-2秒,因为如果用户快速输入单词“test”,网格会重新绑定4次,每个字母一次。 - Nullqwerty
2个回答

5
使用ListCollectionView作为网格的ItemsSource并更新过滤器比重新分配ItemsSource要快得多。
下面的示例通过在搜索词文本属性的setter中刷新视图来过滤100,000行,而没有任何明显的延迟。
视图模型 (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);
                };
        }
    }

视图

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

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


谢谢!Shoe建议的延迟解决了问题,但我也会实施和测试您的建议,看看是否能获得更好的性能。再次感谢。 - Nullqwerty

3
如果你的目标是 .net 4.5,一种选择是在你的 TextBox 上设置 Delay 属性,这将阻止设置源值直到达到某个时间阈值(即等用户停止输入)。
<TextBox Text="{Binding SearchText, Delay=1000}"/>

当用户不再输入时,等待1秒钟后设置源值。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接