WPF:如何排序ListBox的ItemSource而不触发所有控件构造函数?
WPF ListBox 集合变动时重复创建控件的性能优化方案
问题场景
我使用的ListBox控件,其ItemsSource绑定到ObservableCollection<ContainerViewModel>类型的Containers属性,每个列表项通过ContainerUserControl展示。但执行以下操作时,所有ContainerUserControl的构造函数都会被触发,数据量大时会造成严重性能问题:
- 重新赋值排序后的集合
- 调用
Move方法对集合进行原地排序 - 切换
ItemsSource
原因排查
经检查发现,ListBox模板中的ScrollViewer设置了CanContentScroll="False",这个配置会禁用UI虚拟化,导致集合每次变动时都需要重建所有列表项控件,无法复用已创建的控件实例。
解决方案
通过以下两步调整,既能启用UI虚拟化,又能保留原有滚动行为:
- 将ListBox模板内
ScrollViewer的CanContentScroll属性设置为True——这是开启UI虚拟化的必要条件 - 给ListBox添加附加属性
VirtualizingPanel.ScrollUnit="Pixel",确保滚动保持原有的像素级平滑体验
修改后的ListBox示例代码:
<ListBox ItemsSource="{Binding Containers}" VirtualizingPanel.ScrollUnit="Pixel"> <ListBox.Template> <ControlTemplate TargetType="ListBox"> <ScrollViewer CanContentScroll="True" Padding="{TemplateBinding Padding}"> <ItemsPresenter /> </ScrollViewer> </ControlTemplate> </ListBox.Template> <ListBox.ItemTemplate> <DataTemplate> <local:ContainerUserControl /> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
内容的提问来源于stack exchange,提问作者Bardak
相关产品推荐
相关产品推荐

