web-dev-qa-db-fra.com

Comment faire défiler vers le bas de ListBox?

J'utilise un Winforms ListBox comme une petite liste d'événements, et je veux le remplir pour que le dernier événement (en bas) soit visible. SelectionMode est défini sur aucun. L'utilisateur peut faire défiler la liste, mais je préférerais qu'il commence par défiler jusqu'à la fin.

En regardant le manque de support pour des choses comme ScrollIntoView, EnsureVisible, je suppose que je devrai créer un contrôle personnalisé qui hérite de ListBox; mais je ne sais pas quoi faire à partir de là.

Quelques pointeurs?

57
JYelton

Je pense que vous pouvez le faire facilement en définissant la propriété TopIndex de manière appropriée.

Par exemple:

int visibleItems = listBox.ClientSize.Height / listBox.ItemHeight;
listBox.TopIndex = Math.Max(listBox.Items.Count - visibleItems + 1, 0);
85
Jon

Faites défiler vers le bas:

listbox.TopIndex = listbox.Items.Count - 1;

Faites défiler vers le bas et sélectionnez le dernier élément:

listbox.SelectedIndex = listbox.Items.Count - 1;

50
user1032613

C'est ce que j'ai fini avec WPF (.Net Framework 4.6.1):

Scroll.ToBottom(listBox);

Utilisation de la classe d'utilitaires suivante:

public partial class Scroll
{
    private static ScrollViewer FindViewer(DependencyObject root)
    {
        var queue = new Queue<DependencyObject>(new[] { root });

        do
        {
            var item = queue.Dequeue();
            if (item is ScrollViewer) { return (ScrollViewer)item; }
            var count = VisualTreeHelper.GetChildrenCount(item);
            for (var i = 0; i < count; i++) { queue.Enqueue(VisualTreeHelper.GetChild(item, i)); }
        } while (queue.Count > 0);

        return null;
    }

    public static void ToBottom(ListBox listBox)
    {
        var scrollViewer = FindViewer(listBox);

        if (scrollViewer != null)
        {
            scrollViewer.ScrollChanged += (o, args) =>
            {
                if (args.ExtentHeightChange > 0) { scrollViewer.ScrollToBottom(); }
            };
        }
    }
}
1
Sean Vikoren