簡體   English   中英

調用ScrollToBottom()后,ScrollViewer不會停止滾動

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM