2010-02-25 100 views
24

在我的應用程序中,我有一個ListBox與項目。該應用程序是用WPF編寫的。WPF ListBox滾動到自動結束

如何自動滾動到最後添加的項目?我希望ScrollViewer在添加新項目時移動到列表的末尾。

有沒有像ItemsChanged這樣的事件? (我不想用SelectionChanged事件)

回答

29

嘗試此:

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

這只是一個有效的選項,如果最後添加的項目是列表中的最後一項。但最後添加的項目可能會添加在位置0. – 0xBADF00D 2015-07-02 06:27:25

+4

此答案應被接受! @ 0xBADF00D如果是這樣的話,你應該只是'lstBox.SelectedIndex = 0';) – DerpyNerd 2016-03-23 07:37:53

+0

即使有重複的項目也能正常工作,謝謝。 – 2016-06-17 09:04:07

4

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

25

請記住,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); 
+0

謝謝。完美地爲我工作。我認爲你應該刪除chatMessages到類似myListBox的東西。 – 2014-01-05 03:37:45

+2

很好,謝謝。供其他人使用的費用:必須將這些參考文獻添加到您的項目中:UIAutomationProvider和UIAutomationTypes – BCA 2014-10-21 19:51:21

+0

最後經過幾個小時的嘗試和搜索,這對我來說絕對是最好的解決方案。 – ck84vi 2015-10-29 08:36:19

22

要做到這一點最簡單的方法:

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事件中,並且您具有完全自動的自動滾動行爲。

+1

其他解決方案根本不適合我。代碼被執行(在調試中證明),但它對控件的狀態沒有影響。這在第一時間完美運行。 – 2016-01-26 21:59:04

+1

如果您爲'ListBox'使用自定義模板,那麼這可能不起作用,所以要小心。 – 2016-08-16 07:44:43

+0

對於任何想要知道如何將CollectionChanged附加到列表框的人:在'InitializeComponent();'後面你必須添加'((INotifyCollectionChanged).Items).CollectionChanged + = YourListboxCollectionChanged; – MarkusEgle 2018-02-12 13:37:29

14

最好的解決方案是使用ListBox控件內的ItemCollection對象 這個集合是專門爲內容查看器設計的。它有一個預定義的方法來選擇最後一項,並保持光標位置的參考....

myListBox.Items.MoveCurrentToLast(); 
myListBox.ScrollIntoView(myListBox.Items.CurrentItem); 
0

一個稍微不同的方法對那些到目前爲止提出的。

您可以使用ScrollViewerScrollChanged事件並觀察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(); 
     }; 
    } 
} 

這避免了與結合ListBoxItemsSource變化的一些問題。

也可以找到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; 
} 

然後附上該到ListBoxLoaded事件:

<ListBox Loaded="ListBox_OnLoaded" /> 

這可以很容易地修改爲附加屬性,使之更加通用。