2012-06-26 4 views
0

У меня есть привязанный datagridview с около 1/2 миллионами записей и может быть отсортирован по любому столбцу. В GUI пользователь может выбрать любое количество строк (иногда все они с CTRL + A). Из другого источника я получаю большой список идентификаторов записей (до 1000) и должен выяснить, какой из этих идентификаторов соответствует выбранной строке. Я пробовал много подходов, ни один из которых не выполнялся достаточно быстро. Например:быстрый способ найти состояние выбора строки в datagridview

Невозможно заполнить выбранную коллекцию строк и найти совпадение в списке идентификаторов, потому что счетчик SelectedRows может быть порядка 1/2 миллиона.

Я также пробовал прокручивать список идентификаторов (как правило, порядка 1000), и для каждого идентификатора используется BindingSource.Find («Id», Value), который дает мне индекс строки для каждого ID, и я могу затем проверьте, выбрана ли строка. Это отлично работает, если сетка сортируется по идентификатору, но если это не так, производительность Find() слишком бедна, чтобы называться 1000 раз.

Короче говоря, мне нужен быстрый способ найти Row.Selected состояние для 1000 строк с учетом идентификаторов объектов строки. Кажется, DataGridView или DataBinding должны иметь возможность справиться с этим, но это не очевидно. Заранее спасибо!

+0

Только непроверенный комментарий. Привяжите выбранное свойство и затем выполните поиск по данным. – Paparazzi

ответ

1

Я хотел бы попробовать следующее:

  1. Если возможно, используйте ObservableCollection для ItemsSource в DataGridView.
  2. Добавьте привязку к свойству Selected строки к базовому элементу, содержащемуся в ObservableCollection.
  3. Используйте CollectionViewSource Фильтры

Вот это образец делает что-то очень похожее (хотя на много меньше данных, я подозреваю, что это будет работать очень хорошо):

private ICollectionView _CarListView { get; set; } 
private ObservableCollection<Car> _CarList; 
public ObservableCollection CarList 
{ 
    get 
    { 
     if (_CarList == null) 
     { 
      //Code to build the list 

      //For the car filtering 
      this._CarListView = CollectionViewSource.GetDefaultView(_CarList); 
      this._CarListView.Filter = CarFilter; 
     } 
     return _CarList; 
    } 
} 

private bool CarFilter(object item) 
{ 
    Car car = item as Car; 

    if(car.Name.Contains(FilterText)) 
    { 
     return true; 
    } 
    else 
    { 
     return false; 
    } 
} 

В вашем случае, я просто изменит CarFilter (который действительно является Predicate<T>), чтобы вы могли искать свойство, которое вы привязали к свойству Selected в DataGridViewRow. Например, вы можете создать логическое значение IsSelected для типа объекта, содержащегося в ObservableCollection, и просто вернуться туда, где этот элемент является истинным. После того, как у вас есть результат отфильтрованного списка, пройдите через меньший список идентификаторов, которые вы упомянули (около 1000 элементов), и посмотрите, где совпадают идентификаторы. Я бы попытался использовать запрос LINQ для двух коллекций для выполнения этой операции, которая должна быть примерно такой же быстрой, как вы можете получить.

Если все остальное не удается, вы можете вернуться к своей первоначальной технике петли и попробовать параллельную библиотеку для создания Parallel.ForEach, который будет использовать ваш многоядерный процессор для более быстрой работы. Хотя, я бы не переборщил с этим. Кажется, вам нужно сделать один проход, чтобы накапливать выбранные предметы из вашего большого набора, а затем искать каждый выбранный элемент в меньшем наборе.

Смежные вопросы