Listview очень медленно загружает большие списки

#c# #wpf #xaml #listview

#c# #wpf #xaml #listview

Вопрос:

У меня есть приложение WPF, которое выполняет поиск в большом наборе данных и отображает результаты в ListView . Поиск может возвращать небольшой набор результатов, или набор результатов может состоять из тысяч элементов. Поиск в наборе данных и возврат результирующего набора занимает менее секунды. Возвращаемый набор — это ObservableCollection . Мой ListView работает медленно, когда он загружается. ListView Привязан к ObservableCollection в XAML. Это XAML:

 <GroupBox Header="Translations" Grid.Row="2" Margin="10,0,10,8">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition />
      <RowDefinition Height="35" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="150" />
      <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <ListView Grid.ColumnSpan="2"
              ItemsSource="{Binding FoundItems}"
              SelectionMode="Single"
              MaxHeight="2000"
              VirtualizingPanel.IsContainerVirtualizable="True"
              VirtualizingPanel.IsVirtualizing="True">
      <ListView.View>
        <GridView>
          <GridViewColumn Header="Translation File Name" Width="NaN" DisplayMemberBinding="{Binding Path=FileName}" />
          <GridViewColumn Header="English" Width="400" DisplayMemberBinding="{Binding Path=English}" />
          <GridViewColumn Header="International" Width="400" DisplayMemberBinding="{Binding Path=International}" />
        </GridView>
      </ListView.View>
    </ListView>
    <Border Grid.Row="1" Grid.ColumnSpan="2" BorderThickness="1" BorderBrush="{DynamicResource AccentColorBrush}">
      <Grid Margin="5,0">
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="130" />
          <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <RadioButton VerticalAlignment="Center" Content="Search English" IsChecked="{Binding Path=SearchEnglish}" />
        <RadioButton VerticalAlignment="Center" Grid.Column="1" Content="Search International" IsChecked="{Binding Path=SearchInternational}" />
      </Grid>
    </Border>
  </Grid>
</GroupBox>
  

Это свойство модели представления, к которому ListView привязан:

 public ObservableCollection<DataAccess.TranslationItem> FoundItems
{
  get
  {
    return p_FoundItems;
  }
  set
  {
    p_FoundItems = value;
    NotifyOfPropertyChange("FoundItems");

    TranslationsFound = string.Format("{0} translations found", p_FoundItems.Count);
  }
}
  

Это код, который создает коллекцию FoundItems. Для выполнения и создания коллекции требуется всего несколько мс. Проблема скорости определенно не здесь. Для получения списка используется библиотека DLL черного ящика. Затем он создает коллекцию элементов, которые можно использовать в ObservableCollection.

 public List<TranslationItem> SearchList(bool fCaseSensitive, bool fIgnoreAmpersands, bool fExactMatch,
                                        string sSearchLanguage, string sSearchString)
{
  List<TTranslations.TranslationItem> lstFound = null;
  List<TranslationItem> lstReturn = new List<TranslationItem>();

  p_trItems.SearchingFile  = p_trItems_SearchingFile;

  lstFound = p_trItems.SearchList(fCaseSensitive, fIgnoreAmpersands, fExactMatch, sSearchLanguage, sSearchString);

  foreach (TTranslations.TranslationItem tiItem in lstFound)
    lstReturn.Add(new TranslationItem(tiItem));

  return lstReturn;
}
  

В модели представления у меня есть следующий код, который отвечает за настройку FoundItems. Он возвращает коллекцию, возвращенную в ObservableCollection.

   FoundItems = new ObservableCollection<DataAccess.TranslationItem>(p_trItems.SearchList(p_fCaseSensitive, p_fIgnoreAmpersands, p_fExactMatch, p_fSearchEnglish ? "E" : "I", p_sSearchString));
  

Точки останова до и после этой строки кода указывают, что для построения FoundItems требуется всего лишь миллисекунды.

Есть идеи, почему он будет загружаться так медленно? Это преобразование из более старого приложения, где я создаю список вручную, в цикле, и это занимает всего секунду или две загрузки.

Комментарии:

1. Как вы обновляете FoundItems свойство? Если вы очистите его и добавите элементы в цикл, это не будет удивительно.

2. FoundItems — это свойство модели представления, которое предоставляет коллекцию. Создание коллекции занимает менее секунды.

3. Создание этого не проблема, опубликованный вами метод создает List не наблюдаемую коллекцию. Вопрос в том, запускаете ли вы обновления n view, добавляя элементы по отдельности или у вас есть только одно назначение.

4. Я обновил вопрос. Я добавляю список, возвращенный из списка поиска, в ObservableCollection.

5. Это не приведение. В любом случае, это не должно быть проблемой производительности.

Ответ №1:

В итоге это было легко исправить. Я добавил следующее к ListView объявлению:

 ScrollViewer.CanContentScroll="True"
  

Теперь это выглядит так:

     <ListView Grid.ColumnSpan="2"
              ItemsSource="{Binding FoundItems}"
              SelectionMode="Single"
              MaxHeight="2000"
              VirtualizingPanel.IsContainerVirtualizable="True"
              VirtualizingPanel.IsVirtualizing="True"
              ScrollViewer.CanContentScroll="True">
  

Загрузка больших списков заняла не менее минуты, а стала почти мгновенной.