Listview中的添加项目在WPF中太慢

时间:2016-05-04 14:26:48

标签: c# wpf listview listviewitem

我的问题是我需要在WPF中向Listview添加很多项目。在WinForms中,您只需使用BeginUpdate()方法,添加所有内容,最后使用EndUpdate()方法。

那么,在添加每个项目然后一次性绘制所有项目之前,如何在WPF Listview中停止绘图?

 foreach (FilePaths filePath in directoryPath.GetFilePaths())
 {
   GetFileListViewItem(filePath);
 }

在这个GetFileListViewItem方法中,我将项目添加到listview。

private void GetFileListViewItem(FilePaths filePath)
{
        string ext = GetExtension(filePath.GetPath());
        string fileName = GetFileNameWithoutExtension(filePath.GetPath());
        string type = "";
        if (ext != "")
        { 
            type =  ext.ToUpper().Substring(1) + " File";
        }
        else
        {
            type = "Unknown";
        }

        fileListView.Items.Add(new FileListItem
        {
            Name = fileName,
            Type = type
        });
 }

4 个答案:

答案 0 :(得分:1)

我有一个类似的问题并通过延迟添加解决了它,我编码自定义添加,例如500毫秒延迟,如果我在这个时间有更多的添加,所以我等待下一个500毫秒。 这会导致您经常添加太多项目,因此只会在您的表单中进行单一渲染。

答案 1 :(得分:1)

我认为,在处理WPF时,最好远离WinForms心态,直接操纵代码背后的控件。 WPF最大的优势之一是其数据绑定功能。

ListView控件(从它出现的ItemsControl继承的任何内容)实现了UI虚拟化。从此链接:WPF: Data Virtualization

  

当WPF ItemsControl绑定到大型集合数据源时,启用了UI虚拟化,控件将仅为实际可见的项目(以及上面和下面的几个)创建可视容器。这通常只是整个系列的一小部分。当用户滚动时,在项目变得可见时创建新的可视容器,并且当项目不再可见时处置旧容器。启用容器回收后,它将重用可视容器而不是创建和处理,从而避免了对象实例化和垃圾回收开销。   
  
  UI虚拟化意味着控件可以绑定到大型集合,而不会因可视容器而导致大量内存占用。但是,由于集合中的实际数据对象,可能存在大量内存占用。

但是,根据对此question的回答,当数据将ItemsSource属性绑定到集合时,虚拟化似乎只会启动。因此,似乎直接向ListView添加项目正在阻止虚拟化。

答案 2 :(得分:0)

尝试在Dispatcher.BeginInvoke中执行优先级低于DispatcherPriority.Render的代码

这应该在渲染之前添加所有项目。

Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Render, (Action)delegate
{
     GetFileListViewItem(filePath);
});

答案 3 :(得分:0)

使用DataBinding
将ListVies的DataSource绑定到MyFileListItem
神奇的速度将会发生 我认为直接打破虚拟化 它确实绘制了一次,但是您正在生成多个UI更改通知 这只是一个数据绑定

如果要添加和删除,请使用ObservableCollection
如果值将在FileListItem中更改,那么您需要实现iNotifyProperty已更改

private List<FileListItem> myFileListItems;   
public List<FileListItem> MyFileListItems 
{
    get 
    {  
       if (myFileListItems == null) 
       { 
           myFileLinstItems = new List<FileListItem>();
           foreach (FilePaths filePath in directoryPath.GetFilePaths())
           {
               string ext = GetExtension(filePath.GetPath());
               if (String.IsNullOrEmpty(ext)
                  ext = "Unknown";
               else 
                  ext = ext.ToUpper().Substring(1) + " File";
               myFileListItems.Add(new FileListItem
                                   {
                                      Name = GetFileNameWithoutExtension(filePath.GetPath());,
                                      Type = ext
                                   });
           }
       }  
       return myFileListItems;
    }
 }