热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ListView调整列的性能问题(分组)-ListViewResizeColumnsPerformanceIssues(Grouping)

IamexperiencingmajorperformanceissueswithListViewwheneverIimplementgrouping.Ihavefound

I am experiencing major performance issues with ListView whenever I implement grouping. I have found somewhat similar questions on StackOverflow, but none seem to help!

每当我实现分组时,我都会遇到ListView的主要性能问题。我在StackOverflow上发现了一些类似的问题,但似乎都没有帮助!


Here is my current situation (I have simplified my project so there is less noise):

这是我目前的情况(我简化了我的项目,因此噪音更小):

I have a ContentControl with a ListView as the child. The ListView is bound to an ObservableCollection, which is initially empty. As time passes, objects are added to to the collection (in this example, 500 items are added every 10 seconds using a DispatcherTimer). The size of the ObservableCollection will vary, but it's possible the collection could end up being over 25,000 items.

我有一个ContentControl,ListView作为孩子。 ListView绑定到ObservableCollection,它最初是空的。随着时间的推移,对象被添加到集合中(在此示例中,使用DispatcherTimer每10秒添加500个项目)。 ObservableCollection的大小会有所不同,但收集可能最终会超过25,000个项目。

When the ObservableCollection has less than 2000 (not exact figure), column resizing looks like this:

当ObservableCollection小于2000(不是确切的数字)时,列大小调整如下所示:

enter image description here

However, as more objects are added to the ObservableCollection, there is a noticeable drop in performance (you need to scroll down for this to occur).

但是,随着更多对象被添加到ObservableCollection中,性能会明显下降(您需要向下滚动才能实现此目的)。

This will eventually lead to the Application locking up.

这最终将导致应用程序锁定。

I was thinking the problem could be resolved using Virtualization, so I tried using the following:

我认为可以使用Virtualization解决问题,所以我尝试使用以下内容:


However, nothing seems to work!

Not to mention, VirtualizingPanel.IsVirtualizingWhenGrouping="True" causes the ListView to lock up entirely.

但是,似乎什么都没有用!更不用说,VirtualizingPanel.IsVirtualizingWhenGrouping =“True”会导致ListView完全锁定。

I have also looked into Paul McClean's excellent Data Virtualization, however, it does not handle grouping.

我也研究过Paul McClean出色的数据虚拟化,但是它并没有处理分组。


Question: When grouping items in a ListView, is there a way to resize the columns without drastically affecting the Application's performance?

问题:在ListView中对项目进行分组时,是否有办法调整列的大小而不会显着影响应用程序的性能?

Ideally, I would like to reduce memory overhead, so I am all for implementing some sort of asynchronous solution.

理想情况下,我想减少内存开销,所以我全都是为了实现某种异步解决方案。


CODE:

XAML:

XAML:


    
    
    

    
        
            
                
                    
                        
                    
                
            
        
    

CODE-BEHIND:

后台代码:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace ListViewDemo
{
    /// 
    /// Interaction logic for MainWindow.xaml
    /// 
    public partial class MainWindow : ContentControl
    {
        private ObservableCollection eventCollection = new ObservableCollection();

        public MainWindow()
        {
            InitializeComponent();

            DispatcherTimer dispatcherTimer = new DispatcherTimer();
            dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
            dispatcherTimer.Interval = new TimeSpan(0, 0, 10);
            dispatcherTimer.Start();

            ListView1.ItemsSource = eventCollection;
            ListView1.Items.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Descending));
            ListView1.Items.SortDescriptions.Add(new SortDescription("Date", ListSortDirection.Descending));
            ListView1.Items.GroupDescriptions.Add(new PropertyGroupDescription("Seconds"));
        }

        private void dispatcherTimer_Tick(object sender, EventArgs e)
        {
            for(var i = 0; i <500; i++){
                eventCollection.Add(new Event
                {
                    Name = string.Format("Name_{0}", eventCollection.Count),
                    Date = DateTime.Now.ToString("MM.dd.yy HH:mm"),
                    SecOnds= Convert.ToInt32(DateTime.Now.ToString("ss")),
                    Desc = "Description"
                });
            }
        }

        public class Event
        {
            public string Name { get; set; }
            public string Date { get; set; }
            public int Seconds { get; set; }
            public string Desc { get; set; }
        }

    }

}

3 个解决方案

#1


11  

Your performance issue is due to not using IsVirtualizingWhenGrouping

您的性能问题是由于未使用IsVirtualizingWhenGrouping

You mentionned that using IsVirtualizingWhenGrouping was locking your application, and this is a known WPF issue (see : http://connect.microsoft.com/VisualStudio/feedback/details/780146/freeze-when-using-virtualizingpanel-isvirtualizingwhengrouping for more information on this bug happening when having a custom GroupStyle and IsVirtualizingWhenGrouping set to true)

您提到使用IsVirtualizingWhenGrouping锁定您的应用程序,这是一个已知的WPF问题(请参阅:http://connect.microsoft.com/VisualStudio/feedback/details/780146/freeze-when-using-virtualizingpanel-isvirtualizingwhengrouping获取更多信息将自定义GroupStyle和IsVirtualizingWhenGrouping设置为true时发生此错误

Here is a quick workaroung to solve your issue : You just have to add an expander in the GroupStyle ControlTemplate. You'll then be able to use IsVirtualizingWhenGrouping and then have good performances when scrolling/Resizing columns.

以下是解决问题的快速工作方法:您只需在GroupStyle ControlTemplate中添加扩展器即可。然后,您可以使用IsVirtualizingWhenGrouping,然后在滚动/调整列时获得良好的性能。

Here is the code that works on my machine : (I put everything directly in MainWindow to simplify a bit)

这是在我的机器上运行的代码:(我将所有内容直接放在MainWindow中以简化一下)


    

        
    

    
        
            
                
                    
                        
                    
                
            
        
    

EDIT: Here is a ControlTemplate that "hides" the expander. It's the original one from which I removed the unnecessary parts :

编辑:这是一个“隐藏”扩展器的ControlTemplate。这是我删除不必要部分的原始内容:


        
            
                
                    
                        
                    
                    
                        
                    
                
                
            
        
        
            
                
            
            
                
                
                
                    
                        
                    
                
            
            
                
                
                
                    
                        
                    
                
            
            
                
                
                
                    
                        
                    
                
            
            
                
            
        
    

You can use it by setting it in the group style :

您可以通过在组样式中设置它来使用它:


#2


2  

I think the problem is the ObservableCollection that is bound to your ListView and the case that you are adding 500 items per Add(). Each Add will raise 3 events. 2 NotifyPropertyChanged-Events for property Count and property Item[] and one the NotifyCollectionChanged-Event of the Collection, what counts up to 1500 events that are raised.

我认为问题是绑定到ListView的ObservableCollection以及每个Add()添加500个项目的情况。每个Add都会引发3个事件。 2 NotifyPropertyChanged - 属性Count和属性Item []的事件以及Collection的NotifyCollectionChanged-Event,最多可计入1500个引发的事件。

I have exchanged the ObservableCollection with my own derived implementation of ObservableCollection that allows me to add a range of items and raise only 3 events once.

我已经使用我自己的ObservableCollection派生实现交换了ObservableCollection,它允许我添加一系列项目并且只引发一次3个事件。

    public class SmartCollection : ObservableCollection {
        public SmartCollection()
            : base() {

        }

        public SmartCollection(IEnumerable collection)
            : base(collection) {

        }

        public SmartCollection(List list)
            : base(list) {

        }

        public void AddRange(IEnumerable range) {
            foreach (var item in range) {
                Items.Add(item);
            }

            this.OnPropertyChanged(new PropertyChangedEventArgs("Count"));
            this.OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
            this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }

        public void Reset(IEnumerable range) {
            if (range == null) {
                throw new ArgumentNullException("range", "range is null");
            }

            var rangeToAdd = range.ToList();
            this.Items.Clear();

            AddRange(rangeToAdd);
        }
    }

Using my Collection i changed your method to add the elements to the collection

使用我的Collection我改变了你的方法,将元素添加到集合中

private SmartCollection eventCollection = new SmartCollection();

private void dispatcherTimer_Tick(object sender, EventArgs e) {
  List newEvents = new List(500);

  for(var i = 0; i <500; i++){
    newEvents.Add(new Event {
      Name = string.Format("Name_{0}", eventCollection.Count + i),
      Date = DateTime.Now.ToString("MM.dd.yy HH:mm"),
      SecOnds= Convert.ToInt32(DateTime.Now.ToString("ss")),
      Desc = "Description"
    });
  }

  eventCollection.AddRange(newEvents);
}

#3


0  

I'm not sure if this answer will suit, but I did get that performance back after setting the VirtualizingPanel.ScrollUnit property to "Item". The problem is, I had a number of visual glitches, which included seeing the Grouping object overlaying the top row when scrolling row-by-row (mouse wheel or key up/down), and the blurring across the rows immediately after scrolling as the renderer kicked in clear up the text.

我不确定这个答案是否适合,但是在将VirtualizingPanel.ScrollUnit属性设置为“Item”之后我确实得到了这个性能。问题是,我有一些视觉故障,其中包括在逐行滚动(鼠标滚轮或键向上/向下)时看到分组对象覆盖顶行,并在滚动后立即在行之间模糊渲染器开始清理文本。

VirtualizingPanel.ScrollUnit="Item"

Edit: Also change the VirtualizationMode back to Standard, VirtualizingPanel.VirtualizatiOnMode="Standard", and the visual glitches almost dissapear. (Having been testing with 50,000 rows).

编辑:还将VirtualizationMode更改回Standard,VirtualizingPanel.VirtualizatiOnMode=“Standard”,并且视觉故障几乎消失。 (已经测试了50,000行)。


推荐阅读
author-avatar
悸末丶C彼岸花开
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有