WPF ListBox 滚动到自动结束
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2337822/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF ListBox Scroll to end automatically
提问by niao
In my application, I have a ListBox
with items. The application is written in WPF.
在我的应用程序中,我有一个ListBox
项目。该应用程序是用 WPF 编写的。
How can I scroll automatically to the last added item? I want the ScrollViewer
to be moved to the end of the list when new item has been added.
如何自动滚动到最后添加的项目?我希望在ScrollViewer
添加新项目后将其移至列表末尾。
Is there any event like ItemsChanged
?
(I don't want to use the SelectionChanged
event)
有类似的活动ItemsChanged
吗?(我不想使用该SelectionChanged
事件)
回答by Oz Mayt
Try this:
尝试这个:
lstBox.SelectedIndex = lstBox.Items.Count -1;
lstBox.ScrollIntoView(lstBox.SelectedItem) ;
In your MainWindow, this will select and focus on last item on the list!
在您的 MainWindow 中,这将选择并关注列表中的最后一项!
回答by Mateusz My?lak
The easiest way to do this:
最简单的方法:
if (VisualTreeHelper.GetChildrenCount(listView) > 0)
{
Border border = (Border)VisualTreeHelper.GetChild(listView, 0);
ScrollViewer scrollViewer = (ScrollViewer)VisualTreeHelper.GetChild(border, 0);
scrollViewer.ScrollToBottom();
}
It is always working for ListView and ListBox controls. Attach this code to the listView.Items.SourceCollection.CollectionChanged
event and you have fully automatic auto-scrolling behaviour.
它始终适用于 ListView 和 ListBox 控件。将此代码附加到listView.Items.SourceCollection.CollectionChanged
事件中,您将拥有全自动的自动滚动行为。
回答by NovaLogic
Keep in mind that listBox.ScrollIntoView(listBox.Items[listBox.Items.Count - 1]);
works only if you have no duplicate items. If you have items with the same contents it scrolls down to the first find.
请记住,listBox.ScrollIntoView(listBox.Items[listBox.Items.Count - 1]);
只有当您没有重复的项目时才有效。如果您有内容相同的项目,它会向下滚动到第一个查找。
Here is the solution I found:
这是我找到的解决方案:
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);
回答by Givanio
The best solution is to use the ItemCollection object inside the ListBox control this collection was specially designed to content viewers. It has a predefined method to select the last item and keep a cursor position reference....
最好的解决方案是使用 ListBox 控件内的 ItemCollection 对象,该集合是专门为内容查看器设计的。它有一个预定义的方法来选择最后一个项目并保持光标位置参考....
myListBox.Items.MoveCurrentToLast();
myListBox.ScrollIntoView(myListBox.Items.CurrentItem);
回答by Scroog1
A slightly different approach to those presented so far.
与目前介绍的方法略有不同。
You could use the ScrollViewer
ScrollChanged
event and watch for the content of the ScrollViewer
getting larger.
您可以使用该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();
};
}
}
This avoids some issues with the binding to the ListBox
ItemsSource
changing.
这避免了绑定到ListBox
ItemsSource
变化的一些问题。
The ScrollViewer
can also be found without making the assumption that the ListBox
is using the default control template.
该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;
}
Then attach this to the ListBox
Loaded
event:
然后将此附加到ListBox
Loaded
事件:
<ListBox Loaded="ListBox_OnLoaded" />
This could be easily modified to be an attached property, to make it more general purpose.
这可以很容易地修改为附加属性,使其更通用。
回答by JOKe
listBox.ScrollIntoView(listBox.Items[listBox.Items.Count - 1]);
listBox.ScrollIntoView(listBox.Items[listBox.Items.Count - 1]);
回答by Matheus Stumpf
For me, the simplest workingway was this: (without Binding)
对我来说,最简单的工作方式是:(没有绑定)
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]);
}));
}
Don't need to create classes or change the xaml, just write the messages with this method and it scroll automatically.
不需要创建类或更改 xaml,只需使用此方法编写消息并自动滚动。
Calling just
刚打电话
myLv.Items.Add(ls);
myLv.ScrollIntoView(lv.Items[lv.Items.Count - 1]);
for exemple, don't work for me.
例如,不要对我来说有效。
回答by Benny
The most easiest way to achieve autoscrolling is to hook on the CollectionChangedevent. Just add that functionality to a custom class which derives from ListBoxcontrol:
实现自动滚动的最简单方法是挂钩CollectionChanged事件。只需将该功能添加到从ListBox控件派生的自定义类中:
using System.Collections.Specialized;
using System.Windows.Controls;
using System.Windows.Media;
namespace YourProgram.CustomControls
{
public class AutoScrollListBox : ListBox
{
public AutoScrollListBox()
{
if (Items != null)
{
// Hook to the CollectionChanged event of your ObservableCollection
((INotifyCollectionChanged)Items).CollectionChanged += CollectionChange;
}
}
// Is called whenever the item collection changes
private void CollectionChange(object sender, NotifyCollectionChangedEventArgs e)
{
if (Items.Count > 0)
{
// Get the ScrollViewer object from the ListBox control
Border border = (Border)VisualTreeHelper.GetChild(this, 0);
ScrollViewer SV = (ScrollViewer)VisualTreeHelper.GetChild(border, 0);
// Scroll to bottom
SV.ScrollToBottom();
}
}
}
}
Add the namespace of the custom control to your WPF window and use the custom ListBox control:
将自定义控件的命名空间添加到 WPF 窗口并使用自定义 ListBox 控件:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:YourProgram"
xmlns:cc="clr-namespace:YourProgram.CustomControls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<cc:AutoScrollListBox ItemsSource="{Binding YourObservableCollection}"/>
</Window>
回答by Anvaka
You could try ListBox.ScrollIntoView()method, although there are some problemsin some cases...
您可以尝试ListBox.ScrollIntoView()方法,尽管在某些情况下会出现一些问题......
Here is an example from Tamir Khason: Auto scroll ListBox in WPF
下面是来自 Tamir Khason 的一个例子:Auto scroll ListBox in WPF