[英]ScrollViewer will not stop scrolling after calling ScrollToBottom()
我的應用程序中有一個視圖,該視圖在ScrollViewer
中包含ItemsControl
,以顯示日志消息。 作為消息字符串的集合是我的viewmodel中的ObservableCollection<string>
。
添加新消息時, ScrollViewer
需要滾動到列表的底部,具體取決於是否選中了復選框。 我想在視圖中完全解決這個問題。 我找到了一個不錯的解決方案( 在這里 )。 默認情況下,此復選框最初處於選中狀態。
我看到的是奇怪的行為:
我將其簡化為一個非常簡單的WPF應用程序,該應用程序演示了該問題,如下所示。
是什么原因引起的,該如何解決?
XAML:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="229" Width="551">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<CheckBox Grid.Row="0" Content="Autoscroll?" Name="AutoscrollCheckBox" IsChecked="True" />
<Button Grid.Row="1" Content="Add a message" Name="AddMessageButton" Click="AddMessageButton_Click" />
<ScrollViewer Name="MessagesScrollViewer" Grid.Row="2">
<ItemsControl Name="MessagesList" ItemsSource="{Binding Messages}" />
</ScrollViewer>
</Grid>
</Window>
以及后面的代碼:
public partial class MainWindow : Window, INotifyPropertyChanged {
public MainWindow() {
InitializeComponent();
DataContext = this;
((INotifyCollectionChanged)MessagesList.Items).CollectionChanged += Messages_CollectionChanged;
}
private void Messages_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
Console.WriteLine((bool)AutoscrollCheckBox.IsChecked);
if (AutoscrollCheckBox.IsChecked.HasValue && (bool)AutoscrollCheckBox.IsChecked && (e.Action == NotifyCollectionChangedAction.Add))
MessagesScrollViewer.ScrollToBottom();
}
private ObservableCollection<string> m_Messages = new ObservableCollection<string>();
public ObservableCollection<string> Messages {
get { return m_Messages; }
set { m_Messages = value; NotifyPropertyChanged("Messages"); }
}
private int _msgNumber = 0;
private void AddMessageButton_Click(object sender, RoutedEventArgs e) {
Messages.Add(String.Format("Message #{0}", _msgNumber++));
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string name) {
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
這應該是ScrollViewer源代碼的解釋:
如果調用ScrollToBottom
,則Double.PositiveInfinity
值將設置為VerticalOffset
。
/// <summary>
/// Vertically scroll to the end of the content.
/// </summary>
public void ScrollToBottom()
{
EnqueueCommand(Commands.SetVerticalOffset, Double.PositiveInfinity, null);
}
添加新項目后, ScrollViewer
使用最后一個VerticalOffset
(仍然為PositiveInfinity
更新視圖,這意味着它將再次滾動到末尾。 同
var verticalOffset = MessagesScrollViewer.VerticalOffset;
MessagesScrollViewer.ScrollToVerticalOffset(verticalOffset);
ScrollViewer
設置實際的VerticalOffset
,一切都會好起來的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.