Ответ 1
Попробуй это:
lstBox.SelectedIndex = lstBox.Items.Count -1;
lstBox.ScrollIntoView(lstBox.SelectedItem) ;
В вашем MainWindow это выберет и сфокусируется на последнем элементе в списке!
В моем приложении у меня есть ListBox
с элементами. Приложение написано в WPF.
Как я могу автоматически прокручивать последний добавленный элемент? Я хочу, чтобы ScrollViewer
был перемещен в конец списка, когда новый элемент был добавлен.
Есть ли какое-либо событие, например ItemsChanged
?
(Я не хочу использовать событие SelectionChanged
)
Попробуй это:
lstBox.SelectedIndex = lstBox.Items.Count -1;
lstBox.ScrollIntoView(lstBox.SelectedItem) ;
В вашем MainWindow это выберет и сфокусируется на последнем элементе в списке!
Имейте в виду, что 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);
Самый простой способ сделать это:
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
, и у вас есть полностью автоматическое поведение автоматической прокрутки.
Лучшим решением является использование объекта ItemCollection внутри элемента управления ListBox эта коллекция была специально разработана для пользователей контента. Он имеет предопределенный метод для выбора последнего элемента и сохранения ссылки на позицию курсора....
myListBox.Items.MoveCurrentToLast();
myListBox.ScrollIntoView(myListBox.Items.CurrentItem);
listBox.ScrollIntoView(listBox.Items [listBox.Items.Count - 1]);
Несколько иной подход к представленным до сих пор.
Вы можете использовать событие 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" />
Это может быть легко изменено как присоединенное свойство, чтобы сделать его более общей.
Вы можете попробовать метод ListBox.ScrollIntoView(), хотя есть некоторые проблемы в некоторых случаях...
Вот пример из Tamir Khason: Автоматическая прокрутка ListBox в WPF
Для меня самый простой способ работы был такой: (без привязки)
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]);
Например, не работать на меня.