Список с тысячами изображений в обертке
Я пытаюсь создать список, который может содержать более тысячи изображений в виде сетки. С точки зрения дизайна это было бы очень похоже на это:
Поскольку я не могу использовать оболочку, так как это может нарушить виртуализацию пользовательского интерфейса, а панель стека не может отображать изображения в такой сетке (?), Я пытаюсь решить эту проблему с помощью модифицированной версии https://virtualwrappanel.codeplex.com/
Мой XAML:
<ListBox x:Name="GameWheel" ItemsSource="{Binding GameData}" ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Hidden">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<c:VirtualizingWrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Image x:Name="GameImage" Source="{Binding Path=ImagePath}" Width="{Binding ElementName=GameWheel, Path=ActualWidth, Converter={StaticResource widthConverter}}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Хотя этот подход работает, он все еще довольно медленный и глючит, особенно при использовании привязки по ширине изображения. Есть ли лучший способ архивации того же результата? Без кастомной обертки желательно.
1 ответ
Проверьте мою реализацию VirtualizingWrapPanel. Также доступно (с большим количеством включенных) от NuGet.
Этот код изначально взят из этой статьи CodeProject, которая в основном работала и, по-видимому, там же, где вы начали. Попутно я исправил несколько ошибок и улучшил производительность, чтобы она также могла вам помочь.
Обновление: ключ будет связывать с VirtualizingWrapPanel.ItemWidth
скорее, чем Image.Width
, В обеих реализациях была ошибка VirtualizingWrapPanel
это предотвратит изменение размера детей, если ItemHeight
или же ItemWidth
значения изменились. Я исправил эту ошибку в этом коммите (строка 358).
По общему признанию это исправление грубой силы, но я хотел проверить кое-что для Вас и должен выйти. Я проверил это с 10000 изображений, и это было очень быстро. Я поработаю над лучшим решением (т. Е. Буду помнить только тогда, когда мы знаем, что значение изменилось) и обновлю этот ответ, когда я это сделаю.
Обновление 2: Быстрое изменение, чтобы улучшить ребенка. Измерьте этот коммит.
//TODO: If either child Height or Width == PositiveInfinity and the other side == ChildSlotSize then we probably don't need to measure. Need to test this
if (!child.DesiredSize.Equals(ChildSlotSize))
{
child.Measure(ChildSlotSize);
}
Все еще есть возможности для улучшения, но сейчас нет времени для надлежащего тестирования, и это работает.