У меня был обычный Forms.ListView и я преобразовал его в виртуальный список.Реализовал RetrieveVirtualItem
и все работало нормально.
Тогда я решил, что добавлю кеш, и в итоге мне понадобится сортировка, и кто знает, что еще.Так как я унаследовал код, и он уже был несколько беспорядочным, я решил скопировать свои изменения и перенести их в отдельный класс, а именно: наследовать от ListView, например, class MyOwnListView : ListView
, поэтому я переместил егоа также добавил CacheVirtualItems.
После реализации обоих этих методов я заменил:
private System.Windows.Forms.ListView someListView;
на
private MyOwnListView someListView;
в главной форме.
Пока все хорошо ... он работает, но не вылетает (а у меня сейчас только около 60 элементов ...), когда я перемещаю полосу прокрутки, многие из них не перекрашиваются, поэтому выувидеть пустые белые строки, и иногда он будет перекрашивать / показывать после нажатия на эту строку.Я также получаю частично отображаемую и нарисованную строку, например, верхняя часть строки не будет отображаться полностью.
Я не уверен, в чем проблема, я попытался добавить DoubleBuffered=true;
Я также добавилмоему конструктору следующее: (по какому-то предложению я нашел где-то здесь и / или гуглил ..)
SetStyle( ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true );
SetStyle( ControlStyles.EnableNotifyMessage, true );
и этот метод:
protected override void OnNotifyMessage( Message m )
{
//Filter out the WM_ERASEBKGND message
if ( m.Msg != 0x14 )
{
base.OnNotifyMessage( m );
}
}
Мой код в целом оченьпримерно так: .. просто чтобы дать вам представление:
public class MyListView: ListView
{
private ListViewItem[] cache;
private int firstItem;
public MyListView()
{
SetStyle( ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true );
SetStyle( ControlStyles.EnableNotifyMessage, true );
RetrieveVirtualItem += new RetrieveVirtualItemEventHandler( xxx_RetrieveVirtualItem );
CacheVirtualItems += new CacheVirtualItemsEventHandler( xxx_CacheVirtualItems );
}
private void xxx_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
if (cache != null && e.ItemIndex >= firstItem && e.ItemIndex < firstItem + cache.Length)
e.Item = cache[e.ItemIndex - firstItem];
else
e.Item = GetItem(e.ItemIndex);
}
private void xxx_CacheVirtualItems(object sender, CacheVirtualItemsEventArgs e)
{
if (cache != null && e.StartIndex >= firstItem && e.EndIndex <= firstItem + cache.Length)
return;
firstItem = e.StartIndex;
int length = e.EndIndex - e.StartIndex + 1;
cache = new ListViewItem[length];
for (int i = 0; i < cache.Length; i++)
cache[i] = GetItem(firstItem + i);
}
Now, GetItem, basically accesses a List<someobject>, gets the object out of list, and based on that
it creates new ListViewItem and returns it.
}
РЕДАКТИРОВАТЬ: я добавил некоторый код отладки в xxx_CacheVirtualItems.И кажется, что каждый раз, когда я прокручиваю, он возвращается, что элемент не был найден, и снова добавляет его в кэш.Пока не знаю, почему.Я ожидаю, что после первой прокрутки все будет в кеше.Я все еще ищу.
Я также попытался добавить:
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
and tried //Application.SetCompatibleTextRenderingDefault(true);
Это приложение не имело их вообще ... эти две строки сделали что-то интересное.SetCompatibleTextRenderingDefault со значением false вообще не прокручивался, в то время как SetCompatibleTextRenderingDefault со значением true прокручивал, но только вниз и, когда я достиг дна, остановился.но на экране не было проблем с рисованием / обновлением ..