web-dev-qa-db-fra.com

WPF ListBox Faites défiler pour terminer automatiquement

Dans mon application, j'ai un ListBox avec des éléments. L'application est écrite en WPF.

Comment faire défiler automatiquement jusqu'au dernier élément ajouté? Je souhaite que ScrollViewer soit déplacé à la fin de la liste lorsqu'un nouvel élément a été ajouté.

Y a-t-il un événement comme ItemsChanged? (Je ne veux pas utiliser l'événement SelectionChanged)

36
niao

Essaye ça:

lstBox.SelectedIndex = lstBox.Items.Count -1;
lstBox.ScrollIntoView(lstBox.SelectedItem) ;

Dans votre fenêtre principale, cela sélectionnera et se concentrera sur le dernier élément de la liste!

38
Oz Mayt

La façon la plus simple de procéder:

if (VisualTreeHelper.GetChildrenCount(listView) > 0)
{
    Border border = (Border)VisualTreeHelper.GetChild(listView, 0);
    ScrollViewer scrollViewer = (ScrollViewer)VisualTreeHelper.GetChild(border, 0);
    scrollViewer.ScrollToBottom();
}

Il fonctionne toujours pour les contrôles ListView et ListBox. Attachez ce code au listView.Items.SourceCollection.CollectionChanged event et vous avez un comportement de défilement automatique entièrement automatique.

30
Mateusz Myślak

Gardez à l'esprit que listBox.ScrollIntoView(listBox.Items[listBox.Items.Count - 1]); ne fonctionne que si vous n'avez aucun élément en double. Si vous avez des éléments avec le même contenu, il défile jusqu'à la première recherche.

Voici la solution que j'ai trouvée:

ListBoxAutomationPeer svAutomation = (ListBoxAutomationPeer)ScrollViewerAutomationPeer.CreatePeerForElement(myListBox);

IScrollProvider scrollInterface = (IScrollProvider)svAutomation.GetPattern(PatternInterface.Scroll);
System.Windows.Automation.ScrollAmount scrollVertical = System.Windows.Automation.ScrollAmount.LargeIncrement;
System.Windows.Automation.ScrollAmount scrollHorizontal = System.Windows.Automation.ScrollAmount.NoAmount;
//If the vertical scroller is not available, the operation cannot be performed, which will raise an exception. 
if ( scrollInterface.VerticallyScrollable )
    scrollInterface.Scroll(scrollHorizontal, scrollVertical);
28
NovaLogic

La meilleure solution consiste à utiliser l'objet ItemCollection dans le contrôle ListBox, cette collection a été spécialement conçue pour les utilisateurs de contenu. Il a une méthode prédéfinie pour sélectionner le dernier élément et conserver une référence de position du curseur ....

myListBox.Items.MoveCurrentToLast();
myListBox.ScrollIntoView(myListBox.Items.CurrentItem);
20
Givanio

Une approche légèrement différente de celles présentées jusqu'à présent.

Vous pouvez utiliser l'événement ScrollViewerScrollChanged et surveiller que le contenu de ScrollViewer s'agrandit.

private void ListBox_OnLoaded(object sender, RoutedEventArgs e)
{
    var listBox = (ListBox) sender;

    var scrollViewer = FindScrollViewer(listBox);

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

Cela évite certains problèmes avec la liaison à la modification ListBoxItemsSource.

Le ScrollViewer peut également être trouvé sans supposer que le ListBox utilise le modèle de contrôle par défaut.

// Search for ScrollViewer, breadth-first
private static ScrollViewer FindScrollViewer(DependencyObject root)
{
    var queue = new Queue<DependencyObject>(new[] {root});

    do
    {
        var item = queue.Dequeue();

        if (item is ScrollViewer)
            return (ScrollViewer) item;

        for (var i = 0; i < VisualTreeHelper.GetChildrenCount(item); i++)
            queue.Enqueue(VisualTreeHelper.GetChild(item, i));
    } while (queue.Count > 0);

    return null;
}

Attachez ensuite ceci à l'événement ListBoxLoaded:

<ListBox Loaded="ListBox_OnLoaded" />

Cela pourrait être facilement modifié pour être une propriété attachée, pour le rendre plus général.

5
Scroog1

listBox.ScrollIntoView (listBox.Items [listBox.Items.Count - 1]);

4
JOKe

Pour moi, la façon travail le plus simple était la suivante: (sans liaison)

 private void WriteMessage(string message, Brush color, ListView lv)
        {

            Dispatcher.BeginInvoke(new Action(delegate
            {
                ListViewItem ls = new ListViewItem
                {
                    Foreground = color,
                    Content = message
                };
                lv.Items.Add(ls);
                lv.ScrollIntoView(lv.Items[lv.Items.Count - 1]);
            }));
        }

Vous n'avez pas besoin de créer de classes ou de changer le xaml, écrivez simplement les messages avec cette méthode et cela défile automatiquement.

Appeler juste

myLv.Items.Add(ls);
myLv.ScrollIntoView(lv.Items[lv.Items.Count - 1]);

par exemple, ne travaille pas pour moi.

1
Matheus Stumpf

Vous pouvez essayer la méthode ListBox.ScrollIntoView () , bien qu'il y ait des problèmes dans certains cas ...

Voici un exemple de Tamir Khason: ListBox de défilement automatique dans WPF

0
Anvaka