WinForms ListView, помня прокрученное местоположение на перезагрузке
У меня есть представление списка, которое я заполняю 8 столбцами пользовательских данных. Пользователь имеет возможность включить автоматическое обновление, что приводит к тому, что ListView будет очищен и повторно заселен последними данными из базы данных.
Проблема в том, что когда элементы очищаются и повторно заполняются, видимая область возвращается к началу списка. Поэтому, если я смотрю на предмет 1000 из 2000, очень неудобно вернуться к этому элементу.
В основном, я спрашиваю, как мне получить текущие прокрутки (x и y), а затем восстановить их?
Ответы
Ответ 1
У меня была такая же проблема с прошлым, и я закончил реализацию алгоритма сравнения модели со списком, поэтому я только добавил/удалил элементы, которые были изменены. Таким образом, если массовых изменений не было, список не перескочил в начало. И главное, чего я хотел достичь, - это эффективность (чтобы список не мигал).
Ответ 2
Я просто хотел предоставить некоторую информацию тем, кто отчаянно пытается использовать свойство ListView.TopItem с ошибкой:
- Вы ДОЛЖНЫ установить свойство TopItem ПОСЛЕ вызова ListView.EndUpdate
- Элементы элемента управления ListView ДОЛЖНЫ иметь свойство Text для другого
чем String.Empty, или свойство не будет работать.
- Настройка ListView.TopItem периодически прерывает исключения для нулевой ссылки. Всегда держите эту строку кода внутри блока Try... Catch.
Конечно, это приведет к тому, что полоса прокрутки ListView переместится на 0 и вернется к местоположению верхнего элемента, что раздражает. Обновите этот вопрос, если вы найдете обходной путь к этой проблеме.
Ответ 3
Я успешно использовал следующее:
int topItemIndex = 0;
try
{
topItemIndex = listView1.TopItem.Index;
}
catch (Exception ex)
{ }
listView1.BeginUpdate();
listView1.Items.Clear();
//CODE TO FILL LISTVIEW GOES HERE
listView1.EndUpdate();
try
{
listView1.TopItem = listView1.Items[topItemIndex];
}
catch (Exception ex)
{ }
Ответ 4
Свойство TopItemIndex в ListView - это то, что вы ищете, однако оно содержит некоторые подтвержденные ошибки, которые должны были быть рассмотрены в версии VS2010. Не уверен (не проверял).
В любом случае, обходным путем для этой работы является:
listViewOutput.TopItemIndex = outputList.Count - 1;
listViewOutput.TopItemIndex = myNewTopItemIndex;
По какой-то причине установка его напрямую не обновляет, а устанавливает его на последний элемент, а затем тот, который я хочу, надежно работает для меня.
Ответ 5
Посмотрите на свойство ListView.TopItem. Он имеет индекс, который должен содержать свою позицию в списке. Найдите этот индекс в новом списке и установите TopItem на этот элемент, и он должен автоматически выполнять прокрутку.
Ответ 6
К сожалению, вам нужно будет использовать некоторый интерп для прокрутки до точной позиции в ListView. Используйте GetScrollInfo winapi для получения существующей позиции прокрутки и SendMessage, чтобы перейти к позиции.
В статье о CodeProject с именем Прокрутка к группе со списком ListView, которая может помочь вам решить проблему.
Ответ 7
У меня была одна и та же проблема. У меня есть listView, который я заполняю каждые полсекунды, и когда я устанавливаю TopItem в ListItem, чей индекs > видимые элементы, тогда список перепрыгнул между верхним и верхним 2 точками.
Итак, чтобы исправить проблему, я установил TopIterm ПОСЛЕ вызова EndUpdate.
lvB.EndUpdate();
lvI.EndUpdate();
lvR.EndUpdate();
if (lstEntryInts.Items.Count > 0)
lstEntryInts.TopItem = lstEntryInts.Items[iTopVisIdx];
if (lstEntryBools.Items.Count > 0)
lstEntryBools.TopItem = lstEntryBools.Items[iTopVisIdx];
if (lstEntryReals.Items.Count > 0)
lstEntryReals.TopItem = lstEntryReals.Items[iTopVisIdx];
Ответ 8
Мое решение для поддержания положения прокрутки:
Переменная уровня формы:
private static int scrollSpot = 0;
Внутри обновления списка (например, Таймер, кнопка), чтобы сохранить текущее место:
scrollSpot = this.listView1.TopItem.Index;
refreshTheForm();
Внутри refreshTheForm метод, чтобы показать сохраненное место (положить в конце метода):
if (scrollSpot <= 1)
{
listView1.Items[scrollSpot].Selected = true;
}
else
{
listView1.Items[scrollSpot - 2].Selected = true;
}
listView1.TopItem = listView1.SelectedItems[0];
Ответ 9
В моих тестах вам даже не нужен TopItem, хотя я использовал int для сохранения выбранного элемента. Кроме того, TopItem генерирует исключение, если вы используете View.Tile или View.LargeIcon.
Этот код не перемещает полосы прокрутки:
listView1.BeginUpdate();
listView1.Items.Clear();
// loop through your add routine
listView1.Items.Add(lvi);
listView1.EndUpdate();