为什么GridView的加载速度比硬编码的网格慢?

为什么GridView的加载速度比硬编码的网格慢?,gridview,winrt-xaml,uwp,Gridview,Winrt Xaml,Uwp,我在UWP的GridView中遇到了UX性能问题。在我的应用程序中,我需要在单个视图中显示100-200个项目(此处不适用UI虚拟化)。我发现这个GridView在编译调试时第一次导航到页面时大约需要3秒加载,而发布版本则需要5秒加载(我将把这个问题留到下一天!) 我的数据模板并不太复杂,我正在使用x:Bind,甚至尝试了x:Phase,但没有发现显著的改进。然后我尝试了一些古怪的东西:我制作了一个简单的旧网格,并对等价的项进行了硬编码,瞧,加载时间是瞬时的。所以在不涉及技术的情况下,我想使用穷

我在UWP的GridView中遇到了UX性能问题。在我的应用程序中,我需要在单个视图中显示100-200个项目(此处不适用UI虚拟化)。我发现这个GridView在编译调试时第一次导航到页面时大约需要3秒加载,而发布版本则需要5秒加载(我将把这个问题留到下一天!)

我的数据模板并不太复杂,我正在使用x:Bind,甚至尝试了x:Phase,但没有发现显著的改进。然后我尝试了一些古怪的东西:我制作了一个简单的旧网格,并对等价的项进行了硬编码,瞧,加载时间是瞬时的。所以在不涉及技术的情况下,我想使用穷人的网格至少比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;
公共列表假人{get;set;}
(在构造函数中)
列表温度=新列表();
对于(int i=0;i<200;i++)
临时添加(新虚拟(){Number=i});
假人=温度;
我使用了延迟加载策略,并在导航到相关页面时显示了ProgressRing。有200个元素,使用最简单的DataTemplate和model类,progress ring显示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)

... 你明白了(再重复200次)
结果如何?暂停时,页面会立即加载;ProgressRing甚至没有出现。(这是在同一款廉价平板电脑上运行的。)


所以我的最终问题是:当一次显示所有元素时,有没有办法*彻底*提高GridView的性能

加载页面后,可以使用async方法添加项目


显示页面,然后异步加载所有网格项目。

加载页面后,可以使用异步方法添加项目


显示页面,然后异步加载所有网格项。

我很好奇您的
ProgressRing
绑定到的
IsActive
标志是什么?我只是在调用FindName(“LazyContent”)之前在后面的代码中设置IsActive要触发GridView的加载,请记住,
GridView
控件本身比
Grid
复杂得多。虽然同一个
GridView
会在我的开发机器上即时加载,但一次加载数百个项目从来都不是一个好主意。我会使用反应式扩展来加载,比如说,一次加载20个项目,时间跨度
100ms
。使用这种方法,您甚至可以通过应用不透明和向上滑动动画来实现更好的用户体验。@JustinXL,谢谢——我试用了您的方法。不幸的是,这会导致更糟糕的情况:GridView甚至无法跟上100毫秒的间隔,并使系统陷入困境,以至于页面上的其他集合元素无法正确加载。在一天结束时,我最初的问题是:为什么所有这些交错加载的工作环境一开始都是必要的?这不像我通过拨号网络加载项目;一切都在内存中,一切都非常简单。我很好奇您的
ProgressRing
绑定的
IsActive
标志是什么?我只是在调用FindName(“LazyContent”)之前在后面的代码中设置了IsActive要触发GridView的加载,请记住,
GridView
控件本身比
Grid
复杂得多。虽然同一个
GridView
会在我的开发机器上即时加载,但一次加载数百个项目从来都不是一个好主意。我会使用反应式扩展来加载,比如说,一次加载20个项目,时间跨度
100ms
。使用这种方法,您甚至可以通过应用不透明和向上滑动动画来实现更好的用户体验。@JustinXL,谢谢——我试用了您的方法。不幸的是,这会导致更糟糕的情况:GridView甚至无法跟上100毫秒的间隔,并使系统陷入困境,以至于页面上的其他集合元素无法正确加载。在一天结束时,我最初的问题是:为什么所有这些交错加载的工作环境一开始都是必要的?这不像我通过拨号网络加载项目;一切都在记忆中,一切都非常简单。是的,这就是我在做的酷。。。快乐发展:)是的,这就是我在做的酷。。。快乐发展:)