UWP, когда многие GirdView (одна строка включена) вложена в ListView, производительность ListView очень плохая - PullRequest
0 голосов
/ 25 июня 2019

Я создаю такую ​​страницу, как домашняя страница 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 file

используется для загрузки данных из локальной сети:

list.ItemsSource = await GetData();

Итак

Сцена 1:

Запустите приложение с включенной виртуализацией пользовательского интерфейса ListView, процесс связывания выполняется очень быстро и объем памяти составляет около 300 МБ. Затем с помощью мыши быстро прокручивайте ListView вверх / вниз, ListView прокручивает вверх и вниз очень медленно и показывает данные очень медленно после пустого экрана. enter image description here

Сцена 2:

Запустите приложение с отключенной виртуализацией пользовательского интерфейса ListView, на этот раз процесс связывания занимает очень много времени, и объем памяти может увеличиться до 1 ГБ. Но прокручивая вверх / вниз ListView быстро, все в порядке.

Мои потребности:

  • Прокрутка вверх / вниз ListView быстро выполняется быстро.
  • Быстрый процесс привязки и нехватка памяти.

Как исправить?

Как это исправить, большое спасибо. enter image description here

1 Ответ

0 голосов
/ 26 июня 2019

Я хочу, чтобы живое визуальное дерево показывало все элементы ListViewItems, потому что я буду использовать все элементы ListViewItems для выполнения некоторых дополнительных действий.

Чтобы объяснить это поведение, мы могли бы сослаться на виртуализация пользовательского интерфейса , виртуализация пользовательского интерфейса - самое важное улучшение, которое вы можете сделать.

Это означает, что элементы пользовательского интерфейса, представляющие элементы, создаются по требованию. Для элемента управления, связанного с коллекцией из 1000 элементов, было бы напрасной тратой ресурсов на создание пользовательского интерфейса для всех элементов одновременно, поскольку все они не могут отображаться одновременно. ListView и GridView (и другие стандартные элементы управления, производные от ItemsControl) выполняют для вас виртуализацию пользовательского интерфейса. Когда элементы близки к прокрутке (несколько страниц), среда генерирует пользовательский интерфейс для элементов и кэширует их. Когда маловероятно, что элементы будут показаны снова, платформа повторно запрашивает память.

Вы можете отключить его с изменением ItemsPanelTemplate как StackPanel

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

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

Быстрый процесс привязки и нехватка памяти.

Вы можете сделать виртуализацию данных, которая разрезает данные json на части, а затем использовать ListView LoadMoreItemsAsync, чтобы загрузить больше.

...