2016-03-08 60 views
1

我有一个视图/视图模型,只显示“日志条目”列表,最近的项目在顶部。用户还可以打开和关闭几个设置,以限制列表中出现哪些类型的日志条目。问题在于随着日志项数量的增加,应用程序开始运行得越来越慢,并且ItemsControl闪烁并闪烁。我是否正确使用集合视图?

这里是VM代码(为简洁起见除去不相干码):

public class ApplicationLogViewModel 
{ 
    private readonly List<ApplicationLogEntry> _allLogEntries = new List<ApplicationLogEntry>(); 

    // Bound to an ItemsControl in the view 
    public ICollectionView LogEntries { get; private set; } 

    // Ctr 
    public ApplicationLogModel(IApplicationLogService applicationLogService) 
    { 
     LogEntries = CollectionViewSource.GetDefaultView(_allLogEntries); 

     applicationLogService.MessageLogged += MessageLogged; 
    }  

    // Event handler to add new log entries to list 
    private void MessageLogged(object sender, ApplicationLogEntry logEntry) 
    { 
     var count = _allLogEntries.Count; 
     if (count >= 100) 
     { 
      _allLogEntries.RemoveAt(count - 1); 
     } 

     _allLogEntries.Insert(0, logEntry); 

     Dispatcher.CurrentDispatcher.Invoke(() => LogEntries.Refresh()); 
    } 
} 

A“IApplicationLogService”引发事件作为消息记录,并且该事件在MessageLogged()上述方法处理的,简单地增加了将新项目添加到内部集合的开头(因此您可以获取列表顶部的最新项目),然后刷新集合视图(通过Dispatcher完成,因为事件不会在UI线程中引发)。代码还将列表限制为1000个项目,但问题在此之前很长 - 通常约有100个项目。

我省略了设置集合视图的Filter(基于某些布尔属性状态)的代码,因为即使使用LogEntries.Filter = null也会发生减速。

我知道调用Refresh()会导致完整的更新/重绘列表,因此会出现性能问题。所以问题是 - 我是否正确使用集合视图,还是有一种更有效的方法来实现我想要做的事情?

+2

您可以使用ObservableCollection ()并使用数据绑定。然后,无论何时删除/插入项目到ObservableCollection,gui都会注意到这一点。这里有一个小教程:http://www.wpf-tutorial.com/data-binding/responding-to-changes/ –

+0

@ Nitro.de在几分钟前刚刚尝试过,然后才看到您的评论,它可以工作!无需调用Refresh()。发布这个答案,我会标记它。 –

回答

1

最简单的方法是将您的List<ApplicationLogEntry> _allLogEntries更改为ObservableCollection<ApplicationLogEntry> _allLogEntries并在其上使用数据绑定。用户界面会自行注意收藏集中的每一项变化,并将删除/重新加载需要的内容。如果你需要关于数据绑定的一点教程this one here帮了我很多。