Cómo desplazarse automáticamente un cuadro de lista después de agregar un nuevo elemento, pero solo si la barra de desplazamiento está en la parte inferior antes de agregar el elemento?Desplazamiento automático de un cuadro de lista en una situación determinada
Respuesta
Este código de ejemplo debería ser de ayuda. He hecho esto muchas veces con un TextBox, pero me tomó un tiempo encontrarlo en un ListBox
Obviamente, es solo un Formulario con un Botón y un ListBox. Modificar para adaptarse a sus necesidades:
private void button1_Click(object sender, EventArgs e)
{
listBox1.Items.Add("Some Text " + listBox1.Items.Count.ToString());
//The max number of items that the listbox can display at a time
int NumberOfItems = listBox1.ClientSize.Height/listBox1.ItemHeight;
if (listBox1.TopIndex == listBox1.Items.Count - NumberOfItems - 1)
{
//The item at the top when you can just see the bottom item
listBox1.TopIndex = listBox1.Items.Count - NumberOfItems + 1;
}
}
He resuelto este problema utilizando un método similar al colithium, excepto que luego se dio cuenta que había un error con actualizaciones simultáneas. Entonces, hay un miembro de la clase llamado m_previousCount que almacena el número de elementos en el ListBox antes de que ocurriera esta actualización.
Lo hice con un ListView, pero debería funcionar igual para un ListBox.
En este caso, mi listView1 está vinculada al contenido de listViewModel1.Entries.
private void EventMessageViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
listView1.Dispatcher.BeginInvoke(DispatcherPriority.Background, new ScrollToLastItemDelegate(ScrollToLastItem));
}
/// <summary>
/// Scroll to last item, unless you have scrolled up the list
/// </summary>
private void ScrollToLastItem()
{
// Get scrollviewer
Decorator border = System.Windows.Media.VisualTreeHelper.GetChild(listView1, 0) as Decorator;
ScrollViewer scrollViewer = border.Child as ScrollViewer;
double vo = scrollViewer.VerticalOffset;
// assume they are all the same height
ListBoxItem lbi = listView1.ItemContainerGenerator.ContainerFromIndex(0) as ListBoxItem;
//The max number of items that the listbox can display at a time
double NumberOfItemsOnScreen = listView1.ActualHeight/lbi.ActualHeight;
// use previousCount in case we get multiple updates in one go
if (m_previousCount > NumberOfItemsOnScreen) // scrollbar should be active
{
if (vo < (m_previousCount - NumberOfItemsOnScreen)) // you're not at the bottom
{
return; // don't scroll to the last item
}
}
m_previousCount = listView1.Items.Count;
// scroll to the last item
listView1.SelectedItem = listView1.Items.GetItemAt(listViewModel1.Entries.Count - 1);
listView1.ScrollIntoView(listView1.SelectedItem);
}
Se me ocurrió la siguiente solución que también funcionará para las cajas de lista dibujadas por el propietario con elementos de altura variable.
La idea básica es que se dispare si se desplaza hacia abajo utilizando el método IndexToPoint y un punto en la parte inferior del cuadro de lista para ver si el último elemento está en esa posición. Esto tiene un pequeño defecto en que si el último elemento está en la parte inferior pero no es completamente visible, seguirá creyendo que está desplazado hacia abajo.
Utiliza la propiedad TopIndex para desplazarse por el cuadro de lista. Tenga en cuenta que al configurar TopIndex para que sea el último elemento en el cuadro de lista, no lo colocará en la parte superior si hay espacio suficiente para otros elementos. En ese caso, lo pondrá en la parte inferior, que es lo que quieres.
También tiene un código adicional para mantener el número de elementos en la lista a un monto máximo (definido en otra parte por la constante MAX_LISTBOX_ITEMS) eliminando el superior después de que se llene. Cuando lo hace, funciona donde tendrá que desplazarse por la lista para mantener los mismos elementos que se muestran incluso después de eliminar uno. Si no te importa controlar la cantidad de elementos agregados al cuadro de lista, deberías poder eliminar la cláusula if media del código y cualquier mención de la variable 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();
}
Puede a modo de prueba:
listBox1.SelectedIndex = listBox1.Items.Count - 1;
listBox1.SelectedIndex = -1;
Esta es obviamente la mejor solución. –
Si bien esto no responde perfectamente la pregunta, que requiere que el comportamiento de desplazamiento ocurra "solo si la barra de desplazamiento está en la parte inferior antes de agregar el elemento", esta es una excelente solución y me ayudó a lograr lo que estaba buscando. ¡Gracias! –
- 1. Desplazamiento automático en un cuadro de lista de Silverlight
- 2. Cuadro de texto de líneas múltiples con desplazamiento vertical automático
- 3. Retire la barra de desplazamiento en un cuadro de lista
- 4. Desplazamiento automático de la lista de WPF arrastrando
- 5. Deshabilitar el desplazamiento automático RichTextBox
- 6. memo de desplazamiento automático en delphi
- 7. Android: texto de desplazamiento automático en TextView
- 8. JQuery Desplazamiento seleccionable y automático
- 9. Restauración de la posición de desplazamiento exacta de un cuadro de lista en Windows Phone 7
- 10. cuadro de lista para una lista vacía
- 11. desplazamiento automático suave utilizando javascript
- 12. UITextView desplazamiento automático hacia abajo
- 13. QGraphicsView: Deshabilitar el desplazamiento automático
- 14. JScrollPane y JList desplazamiento automático
- 15. git: deshabilita el empuje automático a una determinada rama remota
- 16. ¿Cómo implementar el desplazamiento automático en DataGridView?
- 17. jQuery UI, arrastrable, desplegable, desplazamiento automático
- 18. Prevenir el desplazamiento horizontal automático en TreeView
- 19. selección de programación elementos/Índices en un cuadro de lista
- 20. GWT 2.4 Desplazamiento automático de DataGrid al seleccionar un elemento
- 21. C# Panel con desplazamiento automático - Restablecimiento de la posición de Srollbar en un foco de control
- 22. Desplazamiento automático cuando contentEditable/designMode en un UIWebView
- 23. Desplazamiento automático listboxitems colocado dentro de un listbox
- 24. Vistas de desplazamiento horizontal lista de lista
- 25. cuadro de lista desplazable dentro de una cuadrícula usando tkinter
- 26. Jquery cuadro de lista evento de cambio no se dispara en el teclado de desplazamiento
- 27. C# El desplazamiento automático del panel no funciona
- 28. Aumento automático de una lista genérica utilizando LINQ en C#
- 29. Lanzar una colección de elementos de un cuadro de lista a una lista genérica
- 30. Cómo establecer la altura del cuadro de lista para auto
que añade buttonMultipleAdds_Click para el caso de tener que añadir/eliminar cualquier número de líneas. – huha