我有一个视图/视图模型,只显示“日志条目”列表,最近的项目在顶部。用户还可以打开和关闭几个设置,以限制列表中出现哪些类型的日志条目。问题在于随着日志项数量的增加,应用程序开始运行得越来越慢,并且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()会导致完整的更新/重绘列表,因此会出现性能问题。所以问题是 - 我是否正确使用集合视图,还是有一种更有效的方法来实现我想要做的事情?
您可以使用ObservableCollection()并使用数据绑定。然后,无论何时删除/插入项目到ObservableCollection,gui都会注意到这一点。这里有一个小教程:http://www.wpf-tutorial.com/data-binding/responding-to-changes/ –
@ Nitro.de在几分钟前刚刚尝试过,然后才看到您的评论,它可以工作!无需调用Refresh()。发布这个答案,我会标记它。 –