WPF的DataGrid:CanContentScroll财产造成古怪的行为 [英] WPF DataGrid : CanContentScroll property causing odd behavior

查看:503
本文介绍了WPF的DataGrid:CanContentScroll财产造成古怪的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个解决方案,我根据用户的标准生成一个DataGrid(或多个实例)..每个网格保持接收数据,因为它通过的ObservableCollection进来

i have a solution where i generate a DataGrid (or multiple instances) based on user criteria.. each grid keeps receiving data as it comes in via ObservableCollection

我有问题,是滚动行事怪异。这是波涛汹涌,虽然滚动滚动条会调整它的自我。

the problem i had, was that the scroll acted weird. It was choppy, and scrollbar would resize it self while scrolling.

不是我发现.. CanContentScroll 属性!它彻底修复了怪异的滚动行为给我带来幸福的临时和幸福。

than i found.. CanContentScroll property! It completely fixes the weird scrolling behavior bringing me temporary bliss and happiness.

然而,它会导致2不幸的副作用。

however, it causes 2 unfortunate side effects.


  1. 每当我重新创建网格实例并将其绑定到我的观察的集合,它冻结我的整个窗口,持续5秒。当我的网格长到大的大小,这种延迟可以持续30秒。

  1. whenever i re-create grid instances and bind them to my observable collection, it freezes my entire window for 5 seconds. when my grid grows to a big size, this delay can last for 30 seconds.

当我打电话TradeGrid.ScrollIntoView(TradeGrid.Items(TradeGrid.Items.Count - 1))滚动到的底部,它跳到底部,并比重回巅峰。

when i call TradeGrid.ScrollIntoView(TradeGrid.Items(TradeGrid.Items.Count - 1)) to scroll to the bottom, it jumps to bottom and than back to the top.

有另一种方式也许是为了实现平滑滚动?

is there another way to achieve smooth scrolling perhaps?

推荐答案

您所遇到的区别的物理的滚动和的逻辑的滚动。

You are encountering the differences between physical scrolling and logical scrolling.

当你已经发现,每一种都有其权衡。

As you have discovered, each has its tradeoffs.

物理滚动

物理滚动(CanContentScroll = FALSE)只是像素的推移,这样:

Physical scrolling (CanContentScroll=false) just goes by pixels, so:


  • 视口始终重新presents正是您的滚动程度的相同部分,给你一个平滑滚动的经验,


  • DataGrid的全部​​内容必须有所有模板充分的应用,并进行测量和布置以确定滚动条的大小,装载和高RAM的使用,和
  • 中导致长时间的延迟
  • 它并没有真正滚动的物品,因此不明白ScrollIntoView很好

  • The entire contents of the DataGrid must have all templates fully applied and be measured and arranged to determine the size of the scrollbar, leading to long delays during loading and high RAM usage, and
  • It doesn't really scroll items so it doesn't understand ScrollIntoView very well

逻辑滚动

逻辑滚动(CanContentScroll =真)由项目而不是像素计算其滚动视和程度,所以:

Logical scrolling (CanContentScroll=true) calculates its scroll viewport and extent by items instead of pixels, so:


  • 视口可能显示不同的数目在不同的时间的项目相比,物品中的程度的数目意在视口中的项数而变化,从而引起滚动条长度来改变,以及

  • The viewport may show a different number of items at different times, meaning the number of items in the viewport as compared to the number of items in the extent varies, causing the scrollbar length to change, and

滚动从一个项目移到之间的下一个,决不,导致干滚动

Scrolling moves from one item to the next and never in between, leading to "jerky" scrolling


  • 只要你在引擎盖下使用VirtualizingStackPanel,只需要应用模板和衡量和安排,在目前实际上是可见的物品,以及

  • As long as you're using VirtualizingStackPanel under the hood, it only needs to apply templates and measure and arrange the items that are actually visible at the moment, and

ScrollIntoView要简单得多,因为它只是需要得到正确的项目索引眼帘

ScrollIntoView is much simpler since it just needs to get the right item index into view

它们之间选择

这是仅有的两种经滚动WPF提供的。您必须基于上述权衡二者之间做出选择。一般逻辑滚动是最适合中型到大型数据集和物理滚动是最适合小的。

These are the only two kinds of scrolling provided by WPF. You must choose between them based on the above tradeoffs. Generally logical scrolling is best for medium to large datasets, and physical scrolling is best for small ones.

物理滚动过程中加快载入技巧是让身体滚动要好是包装在具有固定的大小,并将其孩子的可见性设置为隐藏,当它是不可见的自定义装饰您的项目。这prevents的ApplyTemplate,都,测量,直到你准备好它的出现从存在的关于该项目的后裔管制安排。

A trick to speed loading during physical scrolling is to make the physical scrolling better is to wrap your items in a custom Decorator that has a fixed size and sets its child's Visibility to Hidden when it is not visible. This prevents the ApplyTemplate, Measure and Arrange from occuring on the descendant controls of that item until you're ready for it to happen.

一个技巧,使物理滚动的ScrollIntoView更可靠的是两次调用它。一旦立即曾经在DispatcherPriority.ApplicationIdle的调度回调

A trick to make physical scrolling's ScrollIntoView more reliable is to call it twice: Once immediately and once in a dispatcher callback of DispatcherPriority.ApplicationIdle.

制作逻辑滚动滚动条更稳定

如果您所有的项目都是相同的高度,以随时视口中可见将保持不变的项目数量,造成滚动拇指大小保持不变(因为总数量,如果项目的比例不改变)。

If all your items are the same height, the number of items visible in the viewport at any time will stay the same, causing the scroll thumb size to stay the same (because the ratio with total number if items doesn't change).

另外,也可以修改滚动条本身的行为,以便拇指总是计算为固定大小。要做到这一点,没有任何哈克code-背后:

It is also possible to modify the behavior of the ScrollBar itself so the thumb is always calculated to be a fixed size. To do this without any hacky code-behind:


  • 子类跟踪与自己的
  • 来代替在拇指的MeasureOverride位置和大小的计算
  • 更改用于逻辑滚动滚动条来使用你的子类化轨道,而不是常规的一个
  • 滚动条模板
  • 更改的ScrollViewer模板明确设置您的自定义模板,滚动条上的逻辑滚动滚动条(而不是使用默认的模板)

  • 更改为使用显式地设置您的自定义模板的ScrollViewer上的ScrollViewer它创建
  • 列表框模板
  • Subclass Track to replace the calculation of Thumb position and size in MeasureOverride with your own
  • Change the ScrollBar template used for the logical-scrolling ScrollBar to use your subclassed Track instead of the regular one
  • Change the ScrollViewer template to explicitly set your custom ScrollBar template on the logical-scrolling ScrollBar (instead of using the default template)
  • Change the ListBox template to use explicitly set your custom ScrollViewer template on the ScrollViewer it creates

这意味着复制模板很多code FOM的内置WPF模板,所以它不是一个很优雅的解决方案。但另一种情况是使用哈克code-后面要等到所有的模板被扩展,然后找到滚动条,并只需更换与使用您的自定义跟踪一个滚动条的模板。这code。在一些非常棘手的code的成本节约两个大模板(列表框,ScrollViewer中)。

This means copying a lot of template code fom the built-in WPF templates, so it is not a very elegant solution. But the alternative to this is to use hacky code-behind to wait until all the templates are expanded, then find the ScrollBar and just replace the ScrollBar template with the one that uses your custom Track. This code saves two large templates (ListBox, ScrollViewer) at the cost of some very tricky code.

使用不同的面板将是工作的一个更大的量:VirtualizingStackPanel是虚拟化的唯一面板,只有它和StackPanel的逻辑滚动。既然你正在服用VirtualizingStackPanel的虚拟化能力的优势,你将不得不重新实现所有这些加上所有IScrollInfo信息功能加上常规面板功能。我可以做这样的事情,但我会分配一些,也许很多,日内得到它的权利。我建议你​​不试试呢。

Using a different Panel would be a much larger amount of work: VirtualizingStackPanel is the only Panel that virtualizes, and only it and StackPanel to logical scrolling. Since you are taking advantage of VirtualizingStackPanel's virtualization abilities you would have to re-implement all of these plus all IScrollInfo info function plus your regular Panel functions. I could do something like that but I would allocate several, perhaps many, days to get it right. I recommend you not try it.

这篇关于WPF的DataGrid:CanContentScroll财产造成古怪的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆