Я придумала следующее решение, которое также будет работать для нарисованных владельцем списков с элементами переменной высоты.
Основная идея состоит в том, что он выясняет, прокручивается ли он до конца с помощью метода IndexToPoint и точки внизу списка, чтобы увидеть, находится ли последний элемент в этой позиции. Это имеет небольшой недостаток в том, что если последний элемент находится внизу, но не полностью виден, он все равно будет думать, что он прокручен вниз.
Он использует свойство TopIndex для прокрутки списка. Обратите внимание, что при установке TopIndex в качестве последнего элемента в списке он фактически не будет помещать его в верхнюю часть, если есть достаточно места для других элементов. В этом случае он поместит его внизу, что вам и нужно.
У него также есть дополнительный код, чтобы сохранить максимальное количество элементов в списке (определяемое в другом месте константой MAX_LISTBOX_ITEMS), удаляя верхний элемент после его заполнения. Когда он делает это, он работает там, где ему нужно будет прокрутить список, чтобы сохранить те же элементы, которые отображаются даже после его удаления. Если вам не нужно контролировать количество элементов, добавляемых в список, вы сможете удалить среднее условие if из кода и любые упоминания переменной scrollToIndex.
private void AddItemToListBox(ListBox listBox, object newItem)
{
int scrollToIndex = -1;
bool scrollToEnd = false;
//Work out if we should scroll to the end after adding a new item
int lastIndex = listBox.IndexFromPoint(4, listBox.ClientSize.Height - 4);
if ((lastIndex < 0) || (lastIndex == listBox.Items.Count - 1))
{
scrollToEnd = true;
}
//To prevent listbox jumping about as we delete and scroll
listBox.BeginUpdate();
//Work out if we have too many items and have to delete
if (listBox.Items.Count >= MAX_LISTBOX_ITEMS)
{
//If deleting an item, and not scrolling to the end when new item added anyway,
//then we will need to scroll to keep in the same place, work out new scroll index
if (!scrollToEnd)
{
scrollToIndex = listBox.TopIndex - 1;
if (scrollToIndex < 0)
{
scrollToIndex = 0;
}
}
//Remove top item
listBox.Items.Remove(listBox.Items[0]);
}
//Add new item
listBox.Items.Add(newItem);
//Scroll if necessary
if (scrollToEnd)
{
listBox.TopIndex = listBox.Items.Count - 1;
}
else if (scrollToIndex >= 0)
{
listBox.TopIndex = scrollToIndex;
}
listBox.EndUpdate();
}