XAML 在嵌套控件中启用UWP ListView虚拟化

f2uvfpb9  于 2023-05-27  发布在  其他
关注(0)|答案(1)|浏览(192)

我有下面的ScrollViewer,里面有一个StackPanel

<ScrollViewer Grid.Row="1"
              x:Name="testScroll">
    <StackPanel
        x:Name="LezioniPopupStackPanel">
    </StackPanel>
</ScrollViewer>

从代码中,我需要使用扩展器填充stackpanel,扩展器内部有一个自定义的UserControl,基于从API获得的动态数据。自定义用户控件中有一个ListView。
UserControl:

<UserControl
    x:Class="ClassevivaPCTO.Controls.LessonsListView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:ClassevivaPCTO.Controls"
    xmlns:adapters="using:ClassevivaPCTO.Adapters"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:converters="using:ClassevivaPCTO.Converters"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400">

//LessonListViewDataTemplate template redacted for simplicity

    <ListView x:Name="listView" ItemTemplate="{StaticResource LessonListViewDataTemplate}" 
              />
</UserControl>

从API获取一些数据后,将listviews添加到Expander,然后添加到stackpanel的代码:

...
//add an expander control for every subject
foreach (var currentSubject in subjects.Subjects)
{
    //list of lessons for the current subject id
    var subjectLessons = lessons.Lessons
        .Where(lesson => lesson.subjectId == currentSubject.id)
        .ToList();

    //run on ui thread
    await CoreApplication.MainView.Dispatcher.RunAsync(
        CoreDispatcherPriority.Normal,
        async () =>
        {
            var expander = new Expander
            {
                Header = currentSubject.description,
            };

            var listviewlessons = new LessonsListView() { ItemsSource = subjectLessons, };

            expander.Content = listviewlessons;

            LezioniPopupStackPanel.Children.Add(expander);
        }
    );
}

问题是,当加载数据时,仅仅通过将列表视图添加到扩展器,UI就会挂起近10秒。我猜问题是没有启用虚拟化,所以我尝试将listviews的高度设置为100,实际上数据加载时间不到1秒。
我需要列表视图的高度是无限的,但我如何才能启用虚拟化,因为列表视图是在一个扩展器?

xpcnnkqh

xpcnnkqh1#

一次添加过多UI元素,导致UI线程阻塞,因此最好单独加载UI元素。您可以参考以下代码,在第一次展开Expander控件时使用Expander.Expanded Event加载listview。

private void TestButton_OnClick(object sender, RoutedEventArgs e)
{
    //generate 10 random school subjects
    var subjects = new List<string>();

    for (int i = 0; i < 10; i++)
    {
        var subject = "Subject " + i;
        subjects.Add(subject);
    }

    foreach (var subject in subjects)
    {
        var expander = new Expander();
        expander.Header = subject;
        expander.Expanded += Expander_Expanded;
        TestStackPanel.Children.Add(expander);                          
    }

}

private void Expander_Expanded(object sender, EventArgs e)
{
    Expander expander = sender as Expander;
    if (expander.Content != null)
        return;

    var lessons = new List<string>();
    for (int i = 0; i < 250; i++)
    {
        var lesson = "Lesson " + i;
        lessons.Add(lesson);
    }

    var listView = new ListView();
    listView.ItemsSource = lessons;
    expander.Content = listView;
}

相关问题