【问题标题】:Add item in Listview is too slow in WPFWPF中Listview中的添加项目太慢
【发布时间】:2016-05-05 00:49:27
【问题描述】:

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

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

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

在这个GetFileListViewItem 方法中,我将项目添加到列表视图。

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
        });
 }

【问题讨论】:

  • 您正在使用的代码?
  • @ChrisBint - 更新
  • 但这不会一次绘制一个项目。在该调用(和其他调用)完成之前,不会刷新 UI。在绘制 UI 之前,会 100% 处理后面的代码。现在您生成的 UI 更改事件超出了您的需要,但 UI 只绘制了一次。

标签: c# wpf listview listviewitem


【解决方案1】:

我有一个类似的问题,并通过延迟添加解决了它,我编写了一个自定义添加,例如延迟 500 毫秒,如果我在这段时间内有更多添加,那么我等待下一个 500 毫秒。 这会导致当您频繁添加太多项目时,表单中只会出现单个渲染。

【讨论】:

    【解决方案2】:

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

    ListView 控件(从 ItemsControl 继承的任何东西)实现 UI 虚拟化。从此链接:WPF: Data Virtualization

    当 WPF ItemsControl 绑定到大型集合数据源时,启用 UI 虚拟化后,控件只会为实际可见的项目创建可视容器(加上上面和下面的一些)。这通常只是整个集合的一小部分。当用户滚动时,新的可视容器会在项目变得可见时创建,而旧的容器会在项目不再可见时被丢弃。启用容器回收后,它将重用可视容器而不是创建和处置,避免对象实例化和垃圾收集开销。

    UI 虚拟化意味着控件可以绑定到大型集合,而不会因可视容器而导致大量内存占用。但是,由于集合中的实际数据对象,可能会占用大量内存。

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

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        【解决方案4】:

        使用数据绑定
        将 ListVies 的 DataSource 绑定到 MyFileListItem
        神奇的速度会发生
        我认为添加直接中断虚拟化
        它会绘制一次,但您会生成多个 UI 更改通知
        这只是一个数据绑定

        如果要添加和删除,请使用 ObservableCollection
        如果 FileListItem 中的值会发生变化,那么您需要实现 iNotifyProperty changed

        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;
            }
         }
        

        【讨论】:

          猜你喜欢
          • 2013-04-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-03-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多