【发布时间】:2016-01-08 14:29:07
【问题描述】:
我遇到了 UWP 的 GridView 的 UX 性能问题。在我的应用程序中,我需要在单个视图中显示 100-200 个项目(UI 虚拟化在这里不适用)。我发现在为调试编译时,第一次导航到页面时加载此 GridView 大约需要 3 秒,而对于发布版本则需要 5 秒(我将把这个问题留到另一天!)。
我的 DataTemplate 并不过分复杂,我正在使用 x:Bind 甚至尝试过 x:Phase,但没有发现明显的改进。然后我尝试了一些古怪的东西:我制作了一个普通的旧网格并硬编码了等效的项目,瞧——加载时间是瞬时的。因此,在不涉及技术的情况下,我猜使用穷人的 Grid 至少比 GridView 快 100 倍(或 1000 倍?)...使用相同的数据绑定呈现相同的内容。
为了说明这两种方法在性能上的鲜明对比,我创建了一个最简单的示例:从此类开始:
public class Dummy
{
public int Number { get; set; }
}
... 使用以下 XAML:
<GridView Name="LazyContent" x:DeferLoadStrategy="Lazy" ItemsSource="{x:Bind Dummies}" >
<GridView.ItemTemplate>
<DataTemplate x:DataType="local:Dummy">
<Border>
<TextBlock Text="{x:Bind Number}" />
</Border>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
...以及以下代码隐藏:
public List<Dummy> Dummies { get; set; }
(in constructor)
List<Dummy> temp = new List<Dummy>();
for (int i = 0; i < 200; i++)
temp.Add(new Dummy() { Number = i });
Dummies = temp;
我使用延迟加载策略并在导航到相关页面时显示 ProgressRing。有 200 个元素,包括最简单的 DataTemplate 和模型类——进度环显示 2 秒(在廉价平板电脑上运行)。就用户体验而言,这已经是不可接受的,这就是我们正在实现的全部目标:
相比之下,我创建了另一个具有完全相同的布局和数据源的页面,但只是手动构建了元素,如下所示:
<Grid Name="LazyContent" x:DeferLoadStrategy="Lazy" >
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid Grid.Row="0" Grid.Column="0" >
<TextBlock Text="{x:Bind Dummies[0].Number}" />
</Grid>
<Grid Grid.Row="0" Grid.Column="1" >
<TextBlock Text="{x:Bind Dummies[1].Number}" />
</Grid>
<Grid Grid.Row="0" Grid.Column="2" >
<TextBlock Text="{x:Bind Dummies[2].Number}" />
</Grid>
<Grid Grid.Row="0" Grid.Column="3" >
<TextBlock Text="{x:Bind Dummies[3].Number}" />
</Grid>
... you get the idea (repeat another ~200 times)
结果?正如怀疑的那样,页面会立即加载; ProgressRing 甚至没有出现。 (这是在同一台廉价平板电脑上运行的。)
所以我的终极问题是:有没有办法*大幅*一次显示所有元素时提高 GridView 的性能?
【问题讨论】:
-
我很好奇你的
ProgressRing绑定的IsActive标志是什么? -
我只是在调用 FindName("LazyContent") 触发加载 GridView 之前在代码隐藏中设置了 IsActive
-
请记住,
GridView控件本身比Grid复杂得多。尽管相同的GridView会立即加载到我的开发机器上,但一次加载数百个项目绝不是一个好主意。我会使用 Reactive Extensions 一次加载 20 个项目,时间跨度为100ms。使用这种方法,您甚至可以通过应用 opacity 和 slide-up 动画来逐渐显示它们,从而获得更好的用户体验。 -
@JustinXL,谢谢——我试过你的方法。不幸的是,这导致了更糟糕的情况:GridView 甚至无法跟上 100 毫秒的间隔,并且使系统陷入困境,以至于页面上的其他集合元素无法正确加载。归根结底,我最初的问题是:为什么所有这些交错加载的解决方法都是必要的?这不像是通过拨号网络加载项目;一切都在记忆中,一切都非常简单。
标签: gridview winrt-xaml uwp