Как наполнить просмотр списка большим количеством информации без блокировки? - PullRequest
2 голосов
/ 27 июня 2009

Я создаю массив ListViewItems в фоновом потоке, а затем заполняю его в виде списка в потоке интерфейса. Проблема в том, что если массив слишком велик, пользовательский интерфейс блокируется во время обновления списка.

Есть ли способ наполнить просмотр списка небольшим влиянием на пользовательский интерфейс?

Ответы [ 3 ]

8 голосов
/ 27 июня 2009

Если у вас есть много данных, которые вы можете использовать, вы можете использовать их в виртуальном режиме, установив для свойства VirtualMode элемента управления ListView значение true. Это означает, что ListView не будет заполняться в традиционном смысле, но вы будете подключать обработчики событий, чтобы доставлять информацию в представление списка небольшими порциями по мере отображения элементов.

Очень простой пример:

private List<string> _listViewData = new List<string>();
private void toolStripButton1_Click(object sender, EventArgs e)
{
    _listViewData = GetData(); // fetch the data that will show in the list view
    listView1.VirtualListSize = _listViewData.Count; // set the list size
}
// event handler for the RetrieveVirtualItem event
private void listView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
    if (e.ItemIndex >= 0 && e.ItemIndex < _listViewData.Count)
    {
        e.Item = new ListViewItem(_listViewData[e.ItemIndex]);
    }
}

Вам также следует использовать событие CacheVirtualItems.

0 голосов
/ 27 июня 2009

Мои комментарии стали довольно длинными, поэтому я решил сделать это отдельным постом.

Во-первых, +1 для Фредрика Мёрка, использование VirtualMode - путь. Тем не менее, вы теряете некоторые функции, например, Авторазмер столбца, и сортировка легче обрабатывать самостоятельно.

Если это проблема, заполнение рабочего потока может звучать заманчиво. Однако заполнение все равно будет происходить в потоке, который владеет элементом управления списком (то есть практически всегда основным потоком) - .NET делает это видимым, заставляя вас использовать (Begin)Invoke. Кроме того, переключение контекста значительно увеличит общее время, необходимое для заполнения всех элементов, если вы заполняете один за другим, поэтому вы хотите заполнить куски (скажем, 50 элементов за раз, или даже лучше заполнить столько, сколько сможете в миллисекунды). Добавьте к этому дополнительную синхронизацию, необходимую при изменении содержимого, у вас есть довольно сложное решение для не столь звездного результата.

0 голосов
/ 27 июня 2009

Вы также можете использовать методы BeginUpdate и EndUPdate

   listView1.BeginUpdate();
   //Add Values
   listView1.EndUpdate();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...