У меня есть реализация IList
для визуализации содержимого коллекции, этой цели, чтобы избежать хранения целых данных в памяти, поэтому я храню каждый элемент в файле SQLite.
public class DataCollection : IList, INotifyCollectionChanged
{
int IList.IndexOf(object item)
{
if (item == null) return -1;
return IndexOf(item as ElementData);
}
private int IndexOf(ElementData element)
{
try
{
if (element == null)
return -1;
if(!isFiltered)
return element.Id - 1;
//en esta funcion es donde se ejecuta el query
return _elementsCache.FetchIndex(element.Id);
}
catch(Exception e)
{
return -1;
}
}
}
Кажется, всеработает нормально, но когда в коллекции более 200 тыс. элементов, в потоке графического интерфейса начинают возникать проблемы с производительностью.Я обнаружил, что GUI постоянно запрашивает IndexOf
как минимум 70 элементов при каждом изменении значения прокрутки.Я не уверен, почему он запрашивает ~ 70 элементов при каждом изменении значения прокрутки, но он делает это.Коллекция обновляется в режиме реального времени, и у нас есть функция для установки максимального значения прокрутки (автопрокрутка), поэтому каждый раз, когда эта функция обновляет значение прокрутки, сетка начинает вызывать IndexOf
.
* 1008.* Есть две коллекции, одна со всеми данными, а другая с отфильтрованными данными.Самая очевидная проблема - это фильтрованная коллекция, потому что для получения «индекса» элемента он идет в SQLite и выполняет следующий запрос:
SELECT [index] FROM ElementData WHERE ElementId=<elementid>
Этот запрос занимает в среднем 1 мс,поскольку ElementId
является индексом.
Это мой XAML из ListView
:
<ListView x:Name ="FilteredElementsListView"
GridViewColumnHeader.PreviewMouseLeftButtonDown ="GridViewColumnHeaderPreviewMouseLeftButtonDown"
PreviewLostKeyboardFocus ="FilteredElementsListViewPreviewLostKeyboardFocus"
TextOptions.TextFormattingMode ="Display"
TextOptions.TextHintingMode ="Animated"
PreviewKeyDown ="FilteredElementsListViewPreviewKeyDown"
Grid.ColumnSpan ="3"
Margin ="0,0,0,-0.333"
VirtualizingPanel.VirtualizationMode ="Recycling">
Style
для обоих ListView
:
<Style TargetType="{x:Type ListView}">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Background" Value="White" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="FontSize" Value="11" />
<Setter Property="SelectionMode" Value="Extended" />
<Setter Property="Foreground" Value="#333333" />
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="True" />
<Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True" />
<Setter Property="VirtualizingStackPanel.VirtualizationMode" Value="Recycling" />
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.CanContentScroll" Value="true" />
.
.
.
</Style>
Есть идеи, как мне избежать этого постоянного вызова IndexOf при изменении значения прокрутки?