如何有效地实现 ScrollViewer 背景网格?
我目前正在开发一个应用程序,该应用程序根据时间线上的时间戳显示数据项。以下屏幕截图为您提供了一个想法:
(来源:antiserum.ch)
时间线包含索引行十毫秒。它使用 Canvas 在正确的位置呈现数据项,并使用 StackPanel 来显示索引行。
你在截图中看到的正是我想要实现的。但是,为了显示索引行,我当前正在填充 TimeSpan 对象列表,每个对象递增 10 毫秒,以获得完整的数据集持续时间。该列表显示在 ItemsControl 中,并带有一个绘制白线、黑框和文本的项目数据模板。
正如您可以想象的那样,从性能角度来看,这可能是最差的方法,因为 ItemsControl 只包含 1000 个元素,而数据仅 10 秒。
所以我的问题是,如何有效地绘制索引标记?
我已经考虑使用 VirtualizingStackPanel 来显示 TimeSpan 项目。这不是一个选项,因为 ScrollViewer 不直接包含索引列表。看来虚拟化在这种情况下不起作用。
为了澄清起见,这里是我的 xaml 代码片段(我删除了模板和样式代码):
<ScrollViewer x:Name="timelineScroller">
<Grid>
<ItemsControl x:Name="IndexMarkers" ItemsSource="{Binding IndexMarkers}" />
<ItemsControl x:Name="TimelineList" ItemsSource="{Binding Lines}" />
</Grid>
</ScrollViewer>
一个可能的解决方案可能是子类化 ScrollViewer 并在渲染时将索引线和文本绘制到 ScrollViewer 的背景。这应该是高效的,因为它只能渲染实际可见的线条。但是,我没有找到有关如何实现此类渲染定制的信息。
任何想法表示赞赏。
问候, 丹尼尔
I am currently developing an application that shows data items based on their timestamp on a timeline. The following screenshot gives you an idea:
(source: antiserum.ch)
The timeline contains index lines every ten milliseconds. It uses a Canvas to render the data items at the right position, and a StackPanel to display the index lines.
What you see in the sceenshot is exactly what I want to achieve. However, to display the index lines, I am currently populating a list of TimeSpan objects, incremented by 10ms each, to get the complete data set duration. That list is displayed in an ItemsControl with an items data template that draws a white line, a black box and the text.
As you can imagine, this is maybe the worst approach from a performance point of view, because the ItemsControl contains already 1000 elements for only ten seconds of data.
So my question is, how do I draw the index markers efficiently?
I already considered using a VirtualizingStackPanel to display the TimeSpan items. This is not an option, because the ScrollViewer does not contain the index list directly. It seems virtualization does not work in this case.
For clarification, here is a snippet of my xaml code (I removed templating and styling code):
<ScrollViewer x:Name="timelineScroller">
<Grid>
<ItemsControl x:Name="IndexMarkers" ItemsSource="{Binding IndexMarkers}" />
<ItemsControl x:Name="TimelineList" ItemsSource="{Binding Lines}" />
</Grid>
</ScrollViewer>
A possible solution may be to subclass the ScrollViewer and draw the index lines and text to the background of the ScrollViewer when rendering. This should be efficient, as it can only render the lines that are actually visible. However, I didn't find information on how to implement such a rendering customization.
Any ideas are appreciated.
Regards,
Daniel
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我最终采用的方法似乎工作得很好,并且没有任何虚拟化:
索引标记列表是恒定的,但根据当前时间对标记宽度取模进行 RenderTransform-ed。这使得 ScrollViewer 背景随着鼠标移动,并突然跳回到原始位置(这种情况发生在值被模运算“环绕”时)。
剩下要做的就是更新标记的标签这种方法效果非常好,用户无法察觉标签的跳跃。
The approach that I finally took seems to work very well, and without any virtualization:
The list of index markers is constant, but gets RenderTransform-ed according to the current time modulo the marker width. This makes the ScrollViewer background move with the mouse, and suddenly jump back into the original position (this happens just when the value gets "wrapped around" by the modulo operation.
All that remains to be done is updating the labels of the markers at exactly that moment. This approach works so well that the jumps of the labels is not perceivable for the user.
听起来您可能需要明确地实现虚拟化。
请记住,您可能想要池化标记(就像在可能的情况下重用相同的元素一样,因为创建/销毁标记可能会导致一些严重的垃圾收集器抖动,因为它试图清理所有这些对象。
如果您使用 Canvas,则基本上可以在代码中修改画布的子元素以显示您想要的元素(指定它们的坐标)。
It sounds like you might need to implement Virtualization explicitly.
Keep in mind that you might want to pool the markers (as in reuse the same elements where possible because creating / destroying markers might cause some serious garbage collector thrashing as it tries to clean up all of those objects.
If you used a Canvas, you could basically modify the children of the canvas in code to display the elements you want it to (specifying their coordinates).