Проблема прокрутки с большим количеством элементов в списке WinForms

Я заметил проблему с наличием большого количества элементов в элементе управления winforms listbox.

В этом простом тестовом примере у меня есть 120 000 строк, добавленных в список. Первоначально я столкнулся с этим, используя таблицу данных, привязанную к listbox.DataSource, но она также воспроизводима таким образом:

listBox.BeginUpdate();
for(int x = 0; x < 120000; x++)
{
    listBox.Items.Add(x);
}
listBox.EndUpdate();

Когда я нажимаю и перетаскиваю кнопку прокрутки сверху вниз, после того, как я отпускаю мышь, она перемещает кнопку прокрутки в середину полосы прокрутки.

Это скриншот того, куда приземляется кнопка, когда я отпускаю ее точно в нижней части / рядом с ней (я был точен и не держал мышь за пределами полосы прокрутки).

введите здесь описание изображения

Если я сейчас нажму на кнопку полосы прокрутки и переместлю ее на 3/4 длины элемента управления вниз, она снова выскочит примерно на 1/4 длины элемента управления.

Кто-нибудь еще видел это и есть ли известное обходное решение? (правда, я не изучал следующий пункт) есть ли у этого элемента управления параметры динамической загрузки «виртуального режима», такие как datagridview, которые могли бы случайно избавиться от этой странной икоты?


person JHubbard80    schedule 17.09.2014    source источник
comment
код, который вы используете для перетаскивания   -  person MethodMan    schedule 17.09.2014
comment
ListView.VirtualMode Свойство   -  person MethodMan    schedule 17.09.2014
comment
также измените этот `listBox.Items.Add(x);` на `listBox.Items.Add(x.ToString());` и посмотрите, повышает ли это эффективность.. кроме того, что вы реализуете, а также правильно использовать цикл for   -  person MethodMan    schedule 17.09.2014
comment
Чтобы ответить на ваши многочисленные комментарии: я не использую перетаскивание в списке. Рад видеть, что виртуальный режим доступен. Вы случайно не знаете, решает ли установка виртуального режима проблему прокрутки? Вышеупомянутый фрагмент кода был тем, что я только что придумал в качестве примера. Для проблемы прокрутки не имеет значения, добавляю ли я целые числа или строки. (Моя первоначальная проблема возникла в приложении со строками, а не числами)   -  person JHubbard80    schedule 17.09.2014
comment
Я неправильно истолковал ваше перетаскивание как перетаскивание. Что происходит, когда вы меняете код, чтобы добавить x.ToString(). Вы также исследовали, каковы ограничения размера для списка в отношении количества элементов, которые он может содержать. .?   -  person MethodMan    schedule 17.09.2014
comment
да, вы можете использовать Virtual, я опубликую пример   -  person MethodMan    schedule 17.09.2014
comment
Вы знаете, что получаете виртуализацию в WPF? Вы застряли с WinForm?   -  person paparazzo    schedule 17.09.2014
comment
@Blam - я мог бы попробовать создать библиотеку управления WPF и использовать ее в своем приложении winforms. Обходной путь для рассмотрения. Спасибо.   -  person JHubbard80    schedule 18.09.2014


Ответы (3)


Например, если вы хотите сделать это при первой загрузке формы, настройте свойство и его виртуальный размер, используя ListView вместо ListBox.

private void Form1_Load(object sender, EventArgs e)
{
    listView1.VirtualMode = true;
    listView1.VirtualListSize = 12000;
 }
person MethodMan    schedule 17.09.2014

ИМХО, вы решаете не ту задачу. Каков вариант использования такого большого количества элементов в вашем списке. Обычное использование окна со списком заключается в том, что пользователь может выбирать из перечисленного населения. Ваше приложение действительно ожидает, что пользователи будут выбирать определенные элементы из такого большого списка вариантов?

Вы окажете своим пользователям (и своей производительности) услугу, предоставив лучший способ сузить список для выбора.

person cdkMoose    schedule 17.09.2014
comment
Ответ более или менее «да». Существует переход к списку записей и фильтров с использованием строковой функции пользовательского интерфейса, но реализация в том виде, в каком она есть сейчас, список «нуждается» в возможности прокручивать все записи. Я мог бы повторно реализовать его, чтобы отображались записи только по определенной категории, а не по всем категориям (но это могло бы сбивать с толку, поскольку функция фильтра должна была бы игнорировать это), но потенциально у него все равно было бы большое количество записей (но, возможно, максимум 30 000 / категория). Решение для рассмотрения, но я бы предпочел (и пользователи, которых я только что опросил), чтобы оно работало как есть. - person JHubbard80; 18.09.2014
comment
Это подтолкнуло меня к потенциальному обходному пути. Я мог бы использовать небольшой элемент управления с двумя вкладками. Каждый со списком. Один работает для поиска и отображается только тогда, когда пользователь ищет строку поиска, другой пользователь будет вынужден выбрать категорию, и поэтому элемент управления будет отображать меньше записей. Проблема по-прежнему существует, если они ищут таким образом, чтобы возвращались все/большинство записей, но в большинстве случаев это позволит избежать проблемы. Я, вероятно, просто напишу свой собственный контроль позже, чтобы полностью обойти это - person JHubbard80; 18.09.2014
comment
Не зная, что делает ваше приложение и как список на самом деле используется вашими пользователями, трудно сказать, каков правильный ответ. Однако я скажу, что за 20 с лишним лет создания приложений для конечных пользователей я ни разу не нашел приемлемого варианта использования более 100 000 элементов в списке, представляемом пользователю, и никто в моих сообществах пользователей не согласился бы с необходимостью работать с таким длинным списком. Что делать пользователю, если значение, которое ему нужно выбрать, составляет 100 000 элементов вниз по списку? - person cdkMoose; 18.09.2014
comment
Возможно, вы захотите опубликовать что-нибудь на ux.stackexchange.com, чтобы получить отзыв о том, как управлять списком такого размера с точки зрения пользователя. - person cdkMoose; 18.09.2014
comment
Спасибо. Я думаю, что в конечном счете вы правы. Хотя содержимое списка бесполезно без эффективной строки поиска, иногда важно количество совпадающих записей. Мне нужно разделить эти функции, чтобы преодолеть ошибку прокрутки на тот случай, если пользователь захочет прокрутить такое большое количество записей (что, я признаю, было бы безумием, если вы действительно ищете что-то конкретное, а не случайную выборку, которая в это часто то, что пользователи делают, изучая возвращенные записи) - person JHubbard80; 21.09.2014

Я заметил, что список, встроенный в вертикальную полосу прокрутки, может возвращать индекс только из позиции прокрутки до максимального значения 65535. Если элементы добавляются больше, чем это значение, возникает проблема с прокруткой. Тем не менее, вертикальная полоса прокрутки не имеет этой проблемы. Он может прокручиваться максимум до Int32.Max. Я просто использовал элемент управления вертикальной полосой прокрутки вместо встроенной по умолчанию полосы прокрутки ListBox.

Я добавляю еще одну вертикальную полосу прокрутки (vScrollBar1) и помещаю ее в правую часть списка, чтобы закрыть вертикальную полосу прокрутки исходного списка.

Затем добавьте ниже код для вертикальной полосы прокрутки, которую я создаю.

private void vScrollBar1_Scroll(object sender, ScrollEventArgs e) { listbox.TopIndex = 
e.NewValue; }

private void vScrollBar1_MouseEnter(object sender, EventArgs e)
    {
        vScrollBar1.Maximum = listbox.Items.Count;
    }
person user10998913    schedule 01.02.2019