UWP当许多GirdViews(启用一行)嵌套在ListView中时,ListView的性能很差

时间:2019-06-25 04:04:53

标签: xaml listview uwp winrt-xaml uwp-xaml

我正在设计类似NetFlix主页的页面。它有许多(20+)GirdView(启用一行)嵌套在外部ListView中。所有项目都是不确定的,因此必须在运行时生成。 所以我设计如下:

Xaml:

<Page.Resources>
        <DataTemplate x:Key="FirstLevelListViewItemTemplate" x:DataType="model:CategoriesItem">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition/>
                </Grid.RowDefinitions>

                <TextBlock Text="{x:Bind CategoryName}" FontSize="28"/>

                <GridView
                    Grid.Row="1"
                    Height="200"
                    ScrollViewer.HorizontalScrollBarVisibility="Hidden"
                    ScrollViewer.HorizontalScrollMode="Enabled"
                    ScrollViewer.VerticalScrollMode="Disabled"
                    ItemsSource="{x:Bind categories, Mode=OneWay}">
                    <GridView.ItemsPanel>
                        <ItemsPanelTemplate>
                            <ItemsWrapGrid Orientation="Vertical"/>
                        </ItemsPanelTemplate>
                    </GridView.ItemsPanel>
                    <GridView.ItemTemplate>
                        <DataTemplate x:DataType="model:CategoryItem">
                            <controls:ImageEx IsCacheEnabled="True" Width="250" Source="{x:Bind cover_image_url}"/>
                        </DataTemplate>
                    </GridView.ItemTemplate>
                </GridView>
            </Grid>
        </DataTemplate>
    </Page.Resources>

    <!--<ScrollViewer>-->
        <ListView x:Name="list"
                    SelectionMode="None"
                    ItemTemplate="{StaticResource FirstLevelListViewItemTemplate}">
    <!--Disable ListView UI virtualization-->
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel/>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
        </ListView>
    <!--</ScrollViewer>-->

模型文件:

public class CategoriesItem
{
    public string CategoryName { get; set; }
    public List<CategoryItem> categories { get; set; }
}

public class CategoryItem
{
    public string cover_image_url { get; set; }
}

.cs文件

用于从本地加载数据:

list.ItemsSource = await GetData();

所以

场景1:

在启用ListView的用户界面虚拟化的情况下运行应用程序,绑定过程非常快,内存约为300MB。然后,使用鼠标快速上下滚动ListView,ListView会非常缓慢地上下滚动,并在屏幕空白后非常慢地显示数据。 enter image description here

场景2:

在禁用ListView的用户界面虚拟化的情况下运行应用程序,这一次绑定过程需要很长时间,并且内存可能会增加到1GB。但是快速向上/向下滚动ListView都可以。

我的需求:

  • 快速滚动ListView可以快速执行。
  • 绑定过程快速且内存不足。

如何解决?

如何解决此问题,非常感谢。 enter image description here

1 个答案:

答案 0 :(得分:0)

  

我希望实时树形图显示所有ListViewItem,因为我将使用所有ListViewItem做一些额外的事情。

为解释这种行为,我们可以参考UI virtualization,UI虚拟化是您可以做出的最重要的改进。

  

这意味着代表项目的UI元素是按需创建的。对于绑定到1000个项目集合的项目控件,同时创建所有项目的UI会浪费资源,因为无法同时显示所有项目。 ListView和GridView(以及其他标准ItemsControl派生的控件)为您执行UI虚拟化。当项目几乎要滚动到视图中(几页之遥)时,框架会为这些项目生成UI并将其缓存。当不太可能再次显示这些项目时,框架会重新占用内存。

您可以将更改ItemsPanelTemplate更改为StackPanel来关闭它

<ListView>
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel />

        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
</ListView>
  

绑定过程快速且内存不足。

您可以进行数据虚拟化,将json数据切成片,然后使用ListView LoadMoreItemsAsync加载更多数据。