WPF ListBox Прокрутить до конца автоматически - PullRequest
34 голосов
/ 26 февраля 2010

В моем приложении у меня есть ListBox с предметами. Приложение написано в WPF.

Как автоматически перейти к последнему добавленному элементу? Я хочу, чтобы ScrollViewer был перемещен в конец списка после добавления нового элемента.

Есть ли какое-либо событие, подобное ItemsChanged? (Я не хочу использовать событие SelectionChanged)

Ответы [ 8 ]

36 голосов
/ 05 июня 2013

Попробуйте это:

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

В вашем главном окне это выберет и сфокусируется на последнем элементе списка!

30 голосов
/ 10 февраля 2015

Самый простой способ сделать это:

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

Он всегда работает для элементов управления ListView и ListBox. Прикрепите этот код к событию listView.Items.SourceCollection.CollectionChanged, и у вас будет полностью автоматическая автопрокрутка.

28 голосов
/ 19 августа 2013

Имейте в виду, что listBox.ScrollIntoView(listBox.Items[listBox.Items.Count - 1]); работает, только если у вас нет повторяющихся элементов. Если у вас есть предметы с одинаковым содержанием, он прокручивается вниз до первой находки.

Вот решение, которое я нашел:

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);
20 голосов
/ 25 февраля 2015

Лучшее решение - использовать объект ItemCollection внутри элемента управления ListBox. Эта коллекция была специально разработана для зрителей контента. У него есть предопределенный метод для выбора последнего элемента и сохранения ссылки на позицию курсора ....

myListBox.Items.MoveCurrentToLast();
myListBox.ScrollIntoView(myListBox.Items.CurrentItem);
5 голосов
/ 03 октября 2017

Немного другой подход к представленным.

Вы можете использовать событие ScrollViewer ScrollChanged и смотреть, как содержимое ScrollViewer становится больше.

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();
        };
    }
}

Это позволяет избежать некоторых проблем с привязкой к изменению ListBox ItemsSource.

ScrollViewer также можно найти, не предполагая, что ListBox использует шаблон элемента управления по умолчанию.

// 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;
}

Затем присоедините это к событию ListBox Loaded:

<ListBox Loaded="ListBox_OnLoaded" />

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

4 голосов
/ 27 июля 2013

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

1 голос
/ 10 декабря 2018

Для меня самый простой способ работы был следующим: (без привязки)

 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]);
            }));
        }

Не нужно создавать классы или изменять xaml, просто напишите сообщения с помощью этого метода, и он автоматически прокрутится.

Вызов только

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

для примера, не работай для меня.

0 голосов
/ 26 февраля 2010

Вы можете попробовать ListBox.ScrollIntoView () , хотя есть некоторые проблемы в некоторых случаях ...

Вот пример Тамира Хасона: Автоматическая прокрутка ListBox в WPF

...