我正在使用MVVM构建一个wpf应用程序。我有viewModels雇佣延迟加载如下:
public class AssignmentsViewModel
{
List<AssignmentViewModel> _Assignments;
public List<AssignmentViewModel> Assignments
{
get
{
if (_Assignments == null)
_Assignments = new List<AssignmentViewModel>(Data.GetAssignments());
return _Assignments;
}
set { _Assignments = value; }
}
}
public class AssignmentViewModel
{
List<NoteViewModel> _Notes;
public List<NoteViewModel> Notes
{
get
{
if (_Notes == null)
_Notes = new List<NoteViewModel>(Data.GetNotes());
return _Notes;
}
set { _Notes = value; }
}
}
View在ListView中有AssignmentViewModels,在ListBox中有一个带有datatemplate的Notes。
当我显示其中一个有160个项目的AssignmentViewModel时,需要加载1000毫秒。我认为这是因为Notes属性从数据库表中获取了150万行。我查了一下,填充Notes列表只花了60ms。所以我猜这是将160个项目加载到列表框中的数据绑定。但事实并非如此,因为listBoxes虚拟化了他们的内容(我已经窥探它并验证了这些项目是在Virtualizing stackpanel中)。
所以我不知所措,我不知道如何找出额外的940毫秒。
我可以做些什么来追踪这个?性能是关键,我不知道如何改进它。
答案 0 :(得分:3)
在不知道UI是什么样的情况下,UI中的某些内容可能会像BitmapEffects的大量使用一样减慢它。
此外,您可能希望将列表切换为ObservableCollection,binding to that can be significantly faster then a List。
还有一些可以帮助您的好performance profiling工具。
答案 1 :(得分:2)
我们能看到您的XAML吗?
如果您的列表框位于stackpanel(或类似控件)中,则列表框不会虚拟化其条目。
这将虚拟化:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Grid.Row=0>Your label here</Label>
<ListBox Grid.Row=1 Your properties here... />
</Grid>
这不会:
<StackPanel>
<Label>Your label here</Label>
<ListBox Your properties here... />
</StackPanel>
在stackpanel内,列表框将呈现为其最大高度,并依赖于stackpanel进行滚动。 (没有虚拟化)
在网格内部,列表框将呈现为网格行高度并使用其自己的滚动查看器。 (虚拟化)
您也可以在列表框中设置Height或MaxHeight属性,而不是将其放在网格中,但如果您使用的是stackpanel,我怀疑您想要某种类型的自动调整。
请注意,您不能通过将堆叠面板放在网格内来作弊;你的列表框必须能够从某个地方获得最大高度。
答案 2 :(得分:0)
您是否尝试过无延迟加载的测试?
此外,您的DataTemplates / Views对您的商品有多复杂?尝试运行带有简单TextBlock表示的测试,以确保视图的复杂程度。
答案 3 :(得分:0)
我会再看一下SQL并确保你的收藏正在填充。在您枚举结果之前,L2S实际上不会填充。
private IEnumerable<Thing> Method1()
{
return _db.Things.Where(t => t.ID > 500);
}
private void Method2()
{
var things = Method1(); // here, 'things' doesn't really contain anything
// even though you've already done the db fetch
foreach (var thing in things) // 'things' gets populated here.
{
// do something
}
}
ex:返回数据后立即调用.ToList()
。您会在数据层中看到更多活动,这些活动在您的业务或UI层之前可能尚未发生。
答案 4 :(得分:0)
我明白了。我有一个需要文本包装的文本块,因为它有时很大。我在datatemplate中显式设置它的宽度(以便它将包装),并且由于某种原因导致ListBox中的VirtualizingStackPanel实现列表中的所有项目。我将它重新设计为适合它的网格。
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
....
</Grid>
<ListBox Grid.Column="1" ItemsSource="{Binding}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" >
...//DataTemplate
</ListBox>
</Grid>
这导致列表框快速加载。感谢您的回答,他们让我走上了正确的道路。