Как предотвратить вызов IndexOf из ListView при каждом изменении значения прокрутки? - PullRequest
0 голосов
/ 03 мая 2019

У меня есть реализация 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 при изменении значения прокрутки?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...