Я пытаюсь улучшить поведение элемента управления ListBox WPF следующим образом: ListBox ниже автоматически прокручивается вниз, когда новые элементы добавляются. Он делает это, используя показанную функцию ScrollToBottom. Используя отображаемые события предварительного просмотра, если пользователь нажимает на элемент, он останавливает прокрутку, даже если добавлено больше элементов. (Было бы неприятно, если бы он продолжал прокручивать!) Если пользователь вручную прокручивает мышью или колесом, то он останавливает прокрутку таким же образом.WPF ListBox автоматический запуск и остановка прокрутки
Прямо сейчас у меня есть кнопка в коде ниже, который запускает автоматическую прокрутку снова.
Мой вопрос заключается в следующем: Как я могу начать автоматическую прокрутку, если пользователь прокручивает либо ListBox весь путь вниз к нижней, или же эквивалент с помощью колеса мыши или клавиатуры. Вот как мои старые списки Borland использовались для работы из коробки.
using System;
using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
// Note requires .NET framework 4.5
namespace MMP
{
public partial class MainWindow : Window
{
public ObservableCollection<String> data { get; set; }
public MainWindow()
{
InitializeComponent();
data = new ObservableCollection<String>();
DataContext = this;
BeginAddingItems();
}
private async void BeginAddingItems()
{
await Task.Factory.StartNew(() =>
{
for (int i = 0; i < Int32.MaxValue; ++i)
{
if (i > 20)
Thread.Sleep(1000);
AddToList("Added " + i.ToString());
}
});
}
void AddToList(String item)
{
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new Action(() => { data.Add(item); ScrollToBottom(); }));
}
bool autoScroll = true;
public void ScrollToBottom()
{
if (!autoScroll)
return;
if (listbox.Items.Count > 0)
listbox.ScrollIntoView(listbox.Items[listbox.Items.Count - 1]);
}
private void listbox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
autoScroll = false;
Console.WriteLine("PreviewMouseDown: setting autoScroll to false");
}
private void listbox_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
Console.WriteLine("PreviewMouseWheel: setting autoScroll to false");
autoScroll = false;
}
private void startButton_Click(object sender, RoutedEventArgs e)
{
ScrollToBottom(); // Catch up with the current last item.
Console.WriteLine("startButton_Click: setting autoScroll to true");
autoScroll = true;
}
private void listbox_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
// Can this be useful?
}
}
}
<Window x:Class="MMP.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test Scrolling"
FontFamily="Verdana"
Width="400" Height="250"
WindowStartupLocation="CenterScreen">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListBox x:Name="listbox" Grid.Row="0"
PreviewMouseWheel="listbox_PreviewMouseWheel"
PreviewMouseDown="listbox_PreviewMouseDown"
ItemsSource="{Binding data}" ScrollViewer.ScrollChanged="listbox_ScrollChanged"
>
</ListBox>
<StackPanel Orientation="Horizontal" Grid.Row="1" HorizontalAlignment="Right">
<Button x:Name="startButton" Click="startButton_Click" MinWidth="80" >Auto Scroll</Button>
</StackPanel>
</Grid>
</Window>
Отредактировано AutoScrolBehavior.cs, чтобы разрешить одиночное событие колеса мыши остановить прокрутку. – Dean
Я пробовал много разных реализаций этого поведения, и это единственное, что действительно работает так, как я хочу, после небольших адаптаций, чтобы заставить его работать для 'ItemsControl'. –