如何解决WPF ListView SelectedItems性能不佳的问题?

Ale*_*dru 1 .net c# wpf listview

这是我的代码(它在WPF ListView中搜索所有匹配项,然后选择所有匹配项):

            public bool FindAll(LogFilter filter, bool matchCase)
            {
                lastLogFilter = filter;
                lastMatchCase = matchCase;
                MatchSearcher quickSearchSearcher = new MatchSearcher(filter, !matchCase);
                bool foundOnce = false;
                Stopwatch watch = new Stopwatch();
                watch.Start();
                var query = from x in listView.Items.Cast<LogRecord>() where quickSearchSearcher.IsMatch(x, false) select x;
                watch.Stop();
                Console.WriteLine("Elapsed milliseconds to search: {0}.", watch.ElapsedMilliseconds);
                if (query.Count() > 0)
                {
                    foundOnce = true;
                    listView.SelectedItems.Clear();
                    watch.Restart();
                    foreach (LogRecord record in query)
                    {
                        listView.SelectedItems.Add(record);
                    }
                    watch.Stop();
                    Console.WriteLine("Elapsed milliseconds to select: {0}.", watch.ElapsedMilliseconds);
                    listView.ScrollIntoView(query.First());
                }
                return foundOnce;
            }
Run Code Online (Sandbox Code Playgroud)

以下是10,000个ListView项目的结果:

Elapsed milliseconds to search: 0.
Elapsed milliseconds to select: 36385.
Run Code Online (Sandbox Code Playgroud)

所以,很明显我的问题是循环:

foreach (LogRecord record in query)
{
    listView.SelectedItems.Add(record);
}
Run Code Online (Sandbox Code Playgroud)

我觉得必须有一种更好的方法来添加到选定项目列表中,或者至少在已设置所有选定项目之前,阻止列表中的数据模板更新(或类似的操作)。在WPF ListView中尝试以编程方式选择多个项目时,有什么方法可以获得更好的性能?

Cle*_*ens 5

SelectedItems您可以调用该SetSelectedItems方法,而不是将选定的项一个接一个地添加到属性中。不幸的是,该方法受到保护,因此您必须创建一个派生的ListBox使其公开可用:

public class MyListView : ListView
{
    public void SelectItems(IEnumerable items)
    {
        SetSelectedItems(items);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 虽然比单独添加项目要快得多,但对于大型列表来说它仍然会变慢。我可以看到它在调用堆栈中调用“IList.Contains()”,所以它可能仍然是 O(n^2)。MVVM 答案无法与虚拟化一起正常工作,并且我解决这些问题的尝试并未成功,因此以编程方式选择大型列表中的许多项目可能根本不适用于 WPF ListView。(FWIW,如果您不想为此创建子类,也可以使用反射来调用“SetSelectedItems”。) (2认同)