You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌套控件场景下如何启用UWP ListView虚拟化?

//add an expander control for every subject
foreach (var currentSubject in subjects.Subjects)
{
var subjectLessons = lessons.Lessons.Where(lesson => lesson.subjectId == currentSubject.id).ToList();
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秒,测试发现给ListView设置固定高度(如100)时,虚拟化生效,加载耗时不足1秒,但需求是ListView高度自适应,请问如何在嵌套Expander的场景下启用虚拟化?

---

# 解决方案
## 1. 替换外层StackPanel为VirtualizingStackPanel
StackPanel会一次性渲染所有子元素,完全不支持虚拟化,这是卡顿的核心原因。直接替换为`VirtualizingStackPanel`并开启回收式虚拟化:
```xml
<ScrollViewer Grid.Row="1" x:Name="testScroll">
    <VirtualizingStackPanel x:Name="LezioniPopupStackPanel" 
                            VirtualizingPanel.VirtualizationMode="Recycling"
                            VirtualizingPanel.IsVirtualizing="True"/>
</ScrollViewer>

2. 配置ListView的虚拟化与自适应高度

在UserControl的ListView中显式开启虚拟化,同时禁用内部滚动——因为外层已有ScrollViewer,ListView不需要独立滚动,这样才能让高度自适应内容的同时保持虚拟化:

<ListView x:Name="listView" 
          ItemTemplate="{StaticResource LessonListViewDataTemplate}"
          VirtualizingStackPanel.VirtualizationMode="Recycling"
          ScrollViewer.VerticalScrollMode="Disabled"
          ScrollViewer.VerticalScrollBarVisibility="Disabled"/>

3. 延迟加载Expander内的ListView数据

默认展开所有Expander会一次性渲染所有ListView内容,改为默认折叠Expander,仅在用户点击展开时加载对应数据:

foreach (var currentSubject in subjects.Subjects)
{
    var subjectLessons = lessons.Lessons.Where(lesson => lesson.subjectId == currentSubject.id).ToList();
    await CoreApplication.MainView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        var expander = new Expander { Header = currentSubject.description, IsExpanded = false };
        var listviewlessons = new LessonsListView();
        
        // 绑定展开事件,延迟加载数据
        expander.Expanded += (s, e) =>
        {
            listviewlessons.ItemsSource = subjectLessons;
        };
        
        expander.Content = listviewlessons;
        LezioniPopupStackPanel.Children.Add(expander);
    });
}

4. 优化Dispatcher回调逻辑

原代码中Dispatcher回调用了不必要的async,去掉后减少线程切换开销:

// 移除回调内的async,因为没有异步操作
await CoreApplication.MainView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
    // 控件创建与添加逻辑
});

内容的提问来源于stack exchange,提问作者Gabboxl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 09:39:55