Постановка задачи
В коде на C++ CLI есть массив vector<TNativeItem> содержащий несколько тысяч элементов и полностью меняющийся много раз в секунду. Нужен WPF контрол, который будет его отображать. Предположительно ListView обращается по индексу только к видимым элементам (в отличии от DataGrid и TreeView), поэтому он наилучший кандидат. Нужно реализовать ICollection (или ICollectionView) который будет хранить элементы только видимого диапазона, остальные делать нулями, причем при выходе элемента за границы видимого диапазона элемент должен зануляться (см 1). Разбивать элементы на страницы (как это делает VirtualizingCollection) не надо, так как мы их не загружаем с удаленного севера в данном случае, а создаем managed обертки для C++ объектов. За счет этого при обновлении всего массива на C++, будет обновляться только видимый диапазон managed объектов, что позволит достичь приемлемой производительности.
Какие могут быть сложности
- Не очень понятно как занулять элемент при выходе из видимой области.
- Можно попробовать перекрыть у ListView ArrangeOverride и MeasureOverride – именно там устанавливается соответствие между элементами коллекции и рядами в VirtualizingStackPanel, но это всё выглядит достаточно странно, и такая реализация выглядит достаточно криво.
- Всегда при скроллинге и при любом изменении массива делать reset всей коллекции через INotifyCollectionChanged, тогда ListView будет каждый раз заново заполнять видимый диапазон.
- При обновлении массива будет прыгать selected item, как его зафиксировать непонятно.
- В отличии от DataGrid в ListView нет понятия редактирования ряда (BeginEdit/EndEdit), также нет Row Header-а, в котором появляется признак редактирования ряда или признак ошибки валидации данных в ряде. Например, что делать если в ячейке ListView введено невалидное значение, например в числовом поле введены буквы и потом нажат Enter или сфокусирована другая ячейка? DataGrid в этом случае выделяет ячейку красным цветом, подсвечивает Row Header и не даёт редактировать другие ячейки пока не будут введены валидные данные, либо изменения не будут отменены. Самый простой выход – использовать контролы, которые не позволяют вводит невалидные значения.
Оптимальный метод реализации
Нужно реализовать класс Table<T> на С#, который будет обеспечивать доступ к элементу по индексу и по ключу за логарифмическое время на основе B-Tree и index для сортировки по любому критерию. При этом должны поддерживаться интерфейсы ICollection, INotifyCollectionChanged. Затем реализовать ICollectionView у которого Source Collection будет как раз этот Table<T>. Либо использовать ADO.NET DataTable, так как его можно сортировать через DataView (см. http://stackoverflow.com/questions/7315339/sorting-a-ado-net-datatable).