2012-05-09 2 views
2

Что касается элемента управления Virtual ListView в приложении Winforms, что такое ВСЕ функции события RetrieveVirtualItem?Что такое ListView.RetrieveVirtualItem Event - C#

Сценарий: есть объект Dictionary, который действует как мой кеш ListView. И его элементы отображаются в ListView. При щелчке столбца словарь кэша сортируется в памяти, а ListView - Refresh() ed. Влияние на пользовательский интерфейс ListView хорошо сортируется. :)

Но я хочу понять, какова роль события RetrieveVirtualItem, которое запускается при обновлении().

В обработчике RetrieveVirtualItem событий [Кто-то код, :(], следующие сделаны:

  1. на основе RetrieveVirtualItemEventArgs.ItemIndex, получить сообщение из кэша
  2. Set RetrieveVirtualItemEventArgs.Item = retreived пункт выше

Похоже, что то, что сделано в обработчике событий, важно, потому что, если я его вынесу, ListView плачет. В чем смысл этого события?

EDIT Или позвольте мне перефразировать вопрос ... Меня беспокоит, почему после сортировки (и RetrieveVirtualItem обработчика событий) выбранный элемент остается в том месте, где он был до сортировки. I.e. Если я выберу элемент # 5 и сортирую, и если сортировка делает этот элемент последним, я бы предпочел, чтобы после LOW был выбран элемент LAST. Но в моем случае 5-й элемент выбирается после сортировки. Итак, каково поведение по умолчанию RetrieveVirtualItem WRT выбранного элемента?

ответ

2

Виртуальные списки учитывают только индексы. Итак, если 5-й элемент выбран до сортировки, 5-й элемент по-прежнему будет выбран после сортировки. Сам элемент управления не знает, что данные, которые были в пятой строке, теперь находятся в первой строке.

Вы должны программировать, что для себя в методе сортировки:

  1. запомнить, какие элементы были выбраны (помните: вы не можете использовать SelectedItems свойство, когда в виртуальном режиме)
  2. делают вид
  3. найти индексы ранее выбранного элемента теперь живут
  4. выбрать те показатели

Вы можете увидеть все это в действии в ObjectListView - обертку вокруг стандартного .NET ListView.

2

Событие RetrieveVirtualItem используется, когда ListView помещается в виртуальный режим. Вместо сохранения ListViewItems в коллекции Items (как, если это не в виртуальном режиме), при необходимости он создает динамические элементы ListViewItems.

Если вы не обрабатываете событие RetrieveVirtualItem, то в ListViewItems не будет добавлено ListViewItems. Я приложил некоторые примеры кода для типичного метода, написанного для обработки события:

//Dynamically returns a ListViewItem with the required properties; in this case, the square of the index. 
void listView1_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) 
    { 
     //Check if cache has been instantiated yet, and if so, whether the item corresponding to the index requested has been added to the cache already 
     if (myCache != null && e.ItemIndex >= firstItem && e.ItemIndex < firstItem + myCache.Length) 
     { 
      //Return cached item for index 
      e.Item = myCache[e.ItemIndex - firstItem]; 
     } 
     else 
     { 
      //When item not in cache (or cache not available) return a new ListViewItem 
      int x = e.ItemIndex * e.ItemIndex; 
      e.Item = new ListViewItem(x.ToString()); 
     } 
    } 

Этого пример взят из MSDN (http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.virtualmode(v=vs.90).aspx), где дальнейшие детали могут быть найдены.

+0

Вы сказали: «Если вы не обрабатываете событие RetrieveVirtualItem, то ни ListViewItems не будет добавлен в ваш ListView», так, наоборот, это значит, что ВСЕ элементы добавляются этим событием? Кажется, нет, потому что он играет только с 'myCache [e.ItemIndex - firstItem]'. – ViV

+0

Да, все элементы (когда listview находится в виртуальном режиме) будут добавлены этим событием. Этот метод не только полагается на выборку элементов из myCache, как если бы выполнялся код внутри предложения else, создается новый элемент и назначается аргументам событий (e.Item = new ListViewItem()). Другое событие CacheVirtualItems полагается на управление кешем – Richard

4

Виртуальный ListView должен вызывать только RetreiveVirtualItem для строк, которые в настоящее время видны на экране.

При перемещении в ListView, например, вы нажимаете клавишу вниз страницы, ListView будет вычислять то, что должно теперь быть индексом верхней строки, и затем вызовет RetrieveVirtualItem, чтобы ваш код мог предоставить элемент для использования в каждом индексе строки.

Если вы не храните или не храните элементы, которые вы предоставляете с помощью RetrieveVirtualItem, они больше не будут существовать после их прокрутки из списка.

Это то, что означает Virtual в VirtualListView - нет реальных строк, строки являются виртуальными. Вот как он мог отображать список, содержащий сотни тысяч строк, потому что он когда-либо будет содержать только то, как много строк видны на экране.

Фактически ListView похож на окно, которое перемещается вверх и вниз по вашему внутреннему списку данных. Метод RetreiveVirtualItem - это то, что он вызывает для перемещения элементов в это окно по мере продвижения. В нем говорится, что я просто перешел в строку 15 - дайте мне элемент для этой строки. Он перейдет к вызову RetreiveVirtualItem для каждого индекса строки, который будет виден. Если в ListView было 5 строк по высоте на экране, вы получили бы 5 вызовов RetrieveVirtualItem - даже если фактические данные, поддерживающие список, имели 3000 элементов. Каждый раз, когда верхняя строка ListView изменилась (из-за навигации), вы получили бы 5 вызовов RetrieveVirtualItem (это не всегда так, но это правильная идея - например, если вы прокрутите вниз по одной строке, это просто спросите вас о новой последней строке - она ​​также просто отбросит данные, которые использовались для старой верхней строки, прокручиваемой из поля зрения).

Возможно, было бы еще проще объяснить, если мы предположим, что ListView имеет только одну строку на дисплее (это означает, что на экране отображается только одна строка) - при перемещении ListView вверх и вниз список данных (т. е. пользователь перемещает ListView), он будет вызывать RetrieveVirtualItem ровно один раз каждый раз, когда он перемещается в новую строку.

Надежда, что помогает ... Good Luck