【问题标题】:How do I implement a ScrollViewer background grid efficiently?如何有效地实现 ScrollViewer 背景网格?
【发布时间】:2011-04-13 13:45:31
【问题描述】:

我目前正在开发一个应用程序,该应用程序根据时间轴上的时间戳显示数据项。下面的截图给你一个思路:


(来源:antiserum.ch

时间线每十毫秒包含一次索引行。它使用 Canvas 将数据项呈现在正确的位置,并使用 StackPanel 显示索引行。

您在截图中看到的正是我想要实现的。但是,为了显示索引行,我目前正在填充 TimeSpan 对象列表,每个对象递增 10 毫秒,以获得完整的数据集持续时间。该列表显示在 ItemsControl 中,其中包含绘制白线、黑框和文本的项目数据模板。

您可以想象,从性能的角度来看,这可能是最糟糕的方法,因为 ItemsControl 已经包含 1000 个元素,只需要 10 秒的数据。

所以我的问题是,如何有效地绘制索引标记?

我已经考虑过使用 VirtualizingStackPanel 来显示 TimeSpan 项。这不是一个选项,因为 ScrollViewer 不直接包含索引列表。在这种情况下,虚拟化似乎不起作用。

为了澄清,这里是我的 xaml 代码的 sn-p(我删除了模板和样式代码):

<ScrollViewer x:Name="timelineScroller">
  <Grid>
    <ItemsControl x:Name="IndexMarkers" ItemsSource="{Binding IndexMarkers}" />
    <ItemsControl x:Name="TimelineList" ItemsSource="{Binding Lines}" />
  </Grid>
</ScrollViewer>

一种可能的解决方案可能是子类化 ScrollViewer,并在渲染时将索引行和文本绘制到 ScrollViewer 的背景。这应该是有效的,因为它只能渲染实际可见的线条。但是,我没有找到有关如何实现这种渲染自定义的信息。

感谢任何想法。

问候, 丹尼尔

【问题讨论】:

    标签: wpf itemscontrol scrollviewer


    【解决方案1】:

    我最终采用的方法似乎效果很好,并且没有任何虚拟化:

    索引标记列表是恒定的,但会根据当前时间对标记宽度取模来进行 RenderTransform-ed。这使得 ScrollViewer 背景随着鼠标移动,并突然跳回原来的位置(这发生在值被模运算“环绕”时。

    剩下要做的就是在那个时刻更新标记的标签。这种方法效果很好,以至于用户无法感知到标签的跳跃。

    【讨论】:

      【解决方案2】:

      听起来您可能需要显式实现虚拟化。

      请记住,您可能希望合并标记(因为在可能的情况下重用相同的元素,因为创建/销毁标记可能会在尝试清理所有这些对象时导致一些严重的垃圾收集器抖动。

      如果你使用了画布,你基本上可以在代码中修改画布的子元素以显示你想要的元素(指定它们的坐标)。

      【讨论】:

      • 问题是有问题的列表是使用 VirtualizingStackPanel 实现的,但 VSP 无法虚拟化,因为它不是相应 ScrollViewer 的直接子代。因此,即使我自己实现,虚拟化也不会发生。
      猜你喜欢
      • 1970-01-01
      • 2015-05-06
      • 1970-01-01
      • 1970-01-01
      • 2012-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多