在InvalidateVisual()之后没有调用OnRender

时间:2013-06-10 10:46:59

标签: wpf prism onrender

自定义WPF控件会覆盖OnRender。该方法从自定义数据生成并显示路径。数据提供程序使用依赖项属性绑定。当数据发生变化时,依赖属性会为事件注册。此事件又调用InvalidateVisual()。

但是,在InvalidateVisual()之后,并不总是调用OnRender。

我们使用Prism Framework和Region functionallity。所讨论的控件嵌入在这样的区域中,该区域被激活和停用。但是,只要区域处于活动状态,Control的属性“IsVisible”就为true。但是,当调用InvalidateVisual()时,OnRender方法不会被调用...

什么可以阻止调用OnRender方法?

3 个答案:

答案 0 :(得分:2)

我也遇到了这个问题。

上下文

我有一堆基于VirtualizingStackPanel(在ListBox内)的DynamicDataDisplay图形组件的控件。

如果有更多的控件一次可见,但不足以让VirtualizingStackPanel在滚动时开始重新使用它们,那么我会看到D3 AxisControl类的这个问题。由于某种原因,它在OnRender方法中做了很多工作,它试图通过在某些内容发生变化时调用InvalidateVisual来触发。

在问题情况下,问题控件调用InvalidateVisual,但他们永远不会调用MeasureOverride,ArrangeOverride OnRender。有趣的是,大多数控件仍然有效,在一个特定的问题情况下,我得到一组11中的最后3个无法正常工作。值得注意的是,那些3(并且只有那3个)在触发对InvalidateVisual的调用的数据绑定更新之前立即接收到对MeasureOverride的调用。

我的修复

最后,我设法通过添加对InvalidateMeasure的调用以及对InvalidateVisual的调用来修复它。

这是一个可怕的解决方案,但它不是我们应用程序的性能关键部分,所以我似乎正在逃避它。

答案 1 :(得分:0)

如果您的控件的大小保持不变,则不应使用 <select id="menu"> <option>Choose a Day</option> <option id="snd">Sunday</option> <option>Monday</option> <option>Tuesday</option> <option>Wednesday</option> <option>Thursday</option> <option>Friday</option> <option id="strd">Saturday</option> </select>InvalidateMeasure(),因为它们会触发昂贵的重新布局。

WPF是保留的绘图系统。 InvalidateVisual()可能更好地称为OnRender(),因为它实际上并没有绘制。它累积了一组绘图对象,WPF用它来随时绘制UI。奇怪的是,如果您在AccumulateDrawingObjects()期间将DrawingGroup放入DrawingContext,您实际上可以在 OnRender()之后有效地更新 {喜欢。

有关详细信息,请参阅我的答案..

https://stackoverflow.com/a/44426783/519568

答案 2 :(得分:-1)

我也遇到了这个问题。

我有一个控件滚动条,它只在 class SelectableItemWidget extends StatefulWidget { .. .... ... class _SelectableItemWidgetState extends State<SelectableItemWidget> { ... .... Widget build(BuildContext context) { return Consumer<ItemProvider>(builder: (context, itemprovider, child) { .... onTap: () => itemprovider.increase(widget.index), 期间计算出显示所有内容真正需要多少空间,这可能比可用显示空间大,因此需要一个滚动条。 OnRender() 可能会调用一些方法,这些方法最终改变了本来应该以 OnRender() 开始 OnRender() 的滚动条的值。

然而,在 InvalidateVisual() 之后没有再次调用 OnRender()。我想原因是 InvalidateVisual() 设置了一些标志,告诉 WPF 控件需要再次绘制,但是一旦 InvalidateVisual() 完成,该标志就会重置。这里有一些我期望它发生的伪代码:

OnRender()

我没有进一步调查 WPF 是否真的以这种方式工作,但它可以解释为什么 //someCode: control.InvalidateVisual() //code of InvalidateVisual() control.RedrawFlag = true; //WPF some time later: if (control.RedrawFlag){ control.OnRender() //OnRender code //do some stuff //decide control needs to be redrawn //however, RedrawFlag is alreday true! //next line is not changing anything control.RedrawFlag = true; //WPF finished executing control.OnRender control.RedrawFlag = false; } 不会被第二次调用。

我没有浪费更多的时间,而是改变了计算控件内容总宽度的方法,并将这段代码放在OnRender()之外。