【问题标题】:WPF ListView: Custom Scrolling BehaviorWPF ListView:自定义滚动行为
【发布时间】:2011-05-13 23:12:26
【问题描述】:

有没有办法让 ListView 在通过绑定到 ListView 的 ItemsSource 属性更新数据时保持垂直滚动?我似乎无法在 ListView 或其底层 GridView 控件中找到一个属性来实现所需的结果。我希望它滚动,以便用户始终可以看到最新信息。当行添加到控件时,滚动条已经出现,但不显示最新的行。

我应该考虑使用具有自动滚动功能的不同类型的控件吗?我只有两列:一列包含 DateTimes,另一列包含一个简单的字符串。我开始认为我的控制选择可能太有限了。

我的 XAML 大致如下所示:

<ListView ItemsSource="{Binding Updates}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Timestamp" DisplayMemberBinding="{Binding TimeStamp}"/>
            <GridViewColumn DisplayMemberBinding="{Binding UpdateString}" />
        </GridView>
    </ListView.View>
</ListView>

【问题讨论】:

  • 考虑到@Daniel 的回答,您是否希望在需要时让 GridView 能够滚动,即。当它包含的数据不止一个屏幕时,或者您是否希望自动发生滚动本身,以便将较旧的数据推出视口,并在添加时滚动新的数据? @Daniel 回答第一个,但第二个需要动画/EventTriggers。 :)
  • 好点,我应该澄清一下。当有多个数据屏幕时,我需要它滚动,然后在数据填充 GridView 时滚动。我将添加该信息。

标签: wpf listview gridview .net-4.0 wpf-controls


【解决方案1】:

我发现公开ListView 的 ScrollViewer 对象来操纵滚动。我的DataContext 包含一个从ObservableCollection 派生的集合,并且在后面的代码中我将一个事件处理程序连接到CollectionChanged 事件。我使用Decorator 暴露ListView(边界)的第一个孩子,它的孩子是ScrollViewer。从那里我调用ScrollToBottom() 方法来获得所需的行为。

在包含ListView 的视图后面的代码中,它是这样编码的

MyViewModel viewModel = DataContext as MyViewModel;

viewModel.MyCollection.CollectionChanged += (sender,e) =>
{
    if(e.NewItems != null)
    {
        Decorator border = VisualTreeHelper.GetChild(SummaryListView, 0) as Decorator;
        ScrollViewer scroll = border.Child as ScrollViewer;
        scroll.ScrollToBottom();
    }
};

我找到了如何在Anshulee's WindowsClient blog post 上公开ScrollViewer。

编辑 以前,我正在检查是否满足自定义集合中的最大项目数,然后滚动到底部。这在不同的屏幕分辨率下效果不佳,因为该应用程序可能在一台机器上在ListView 中显示 15 行,而在另一台机器上显示 25 行。所以现在我总是让它滚动到底部以显示最新的项目。

【讨论】:

    【解决方案2】:

    Listview 有一个名为ScrollIntoView(object item) 的方法。

    这会将 Listview 滚动到指定项所在的位置。

    当您有一个绑定到 Listview 的集合时,您可以在您的集合发生更改时调用此方法,例如:

    private void myCollectionChanged()
    {
        myListView.ScrollIntoView(myCollection.Last());
    }
    

    【讨论】:

    • 我也试过这个方法,它没有滚动到底部项目。我接受的答案(以及我提供的答案)在我的申请中有效。
    • 是的,因为这比我必须做的要简单得多。我更喜欢简单易读,以尽量减少复杂性。
    【解决方案3】:

    我很确定 VirtualizingStackPanel 正在被使用在幕后……这意味着这些项目在需要之前是不存在的。因此,如果您有 15000 个项目,那么在需要之前渲染这 15000 个项目是没有意义的。

    一种更简单的方法可能是强制进行排序,以便最新数据保留在顶部。然后它会给你一个向下推项目的外观,但它们将是最旧的项目,因此除非用户启动它,否则滚动查看它们并不重要。

    【讨论】:

      【解决方案4】:

      你应该使用一个scrollviewer对象,它会在需要时自动滚动它的内容(你也可以指定你是否总是想要水平或垂直滚动​​,不管它在哪里需要,以及其他一些东西)

      <ScrollViewer>
         <GridView>
             <!-- gridview definition -->
         <GridView>
      </ScrollViewer>
      

      更多信息MSDN

      【讨论】:

      • 不幸的是,这对我不起作用,因为 GridView 标题会滚动到视图之外。
      • 任何方式我都可以只包装项目而不是整个 GridView。我想避免将标题滚动到视野之外。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 2017-08-10
      • 1970-01-01
      • 2021-07-17
      • 2011-10-16
      相关资源
      最近更新 更多