ListBox, VirtualizingStackPanel и плавная прокрутка в WPF
У меня есть ListBox
которые могут иметь много строк шаблонных записей БД, в том числе Image
привязанный к ObservableCollection<MyItem>
, Иногда коллекция может содержать тысячи предметов.
Производительность отличная, но прокрутка - это поведение по умолчанию. Я бы хотел, чтобы у него была плавная прокрутка, поэтому я снял флажок ScrollViewer.CanContentScroll
,
Теперь у меня плавная прокрутка, но производительность ужасна: данные извлекаются в отдельном потоке, и поток быстро завершается, но для отображения результатов в течение 10-20 секунд ListBox
, Я предполагаю, что это потому, что снятие отметки ScrollViewer.CanContentScroll
изменяет базовый VirtualizingStackPanel
к регулярному StackPanel
и поэтому он загружает всю коллекцию перед отображением результатов.
Итак, мой вопрос заключается в следующем: как сохранить плавную прокрутку, не жертвуя VirtualizingStackPanel
поведение и производительность?
3 ответа
Когда вы снимаете галочку с CanContentScroll, вы теряете виртуализацию. И ответ действительно расстраивает: пока нет готового решения:(.
PS: Это не первый пост здесь, задающий этот самый вопрос.
Если вы используете.NET 4.5 (или 4.0, если хотите немного взломать), здесь есть ответ.
[Обратите внимание, что комментарий @Guilluame был здесь задолго до этого ответа, но он не был особенно заметен при поиске ответов.]
Для тех, кто ищет в 2021 году, вы можете использовать такое решение:
Вы будете продолжать прокручивать и виртуализировать одновременно
<ItemsControl x:Name="TestIC" Grid.Row="1"
ScrollViewer.CanContentScroll="True"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.VirtualizationMode="Recycling" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Template>
<ControlTemplate>
<Border
Padding="{TemplateBinding Control.Padding}"
Background="{TemplateBinding Panel.Background}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
BorderThickness="{TemplateBinding Border.BorderThickness}"
SnapsToDevicePixels="True">
<ScrollViewer Padding="{TemplateBinding Control.Padding}" Focusable="False">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>