>自定义 WPF 控件覆盖 OnRender。该方法从自定义数据生成并显示路径。数据提供程序使用依赖项属性绑定。依赖项属性在数据更改时注册事件。此事件依次调用 InvalidateVisual((。
但是,在 InvalidateVisual(( 之后,OnRender 并不总是被调用。
我们使用棱镜框架和区域功能。有问题的控件嵌入在此类区域中,该区域已激活和停用。但是,只要区域处于活动状态,控件的属性"IsVisible"就为 true。但是,当调用InvalidateVisual((时,不会调用OnRender方法...
什么可以阻止调用 OnRender 方法?
我也有这个问题。
上下文
我有一个基于VirtualizingStackPanel(在ListBox内(中的DynamicDataDisplay图形组件的控件负载。
当同时可以看到更多控件,但不足以让 VirtualizingStackPanel 在您滚动时开始重用它们时,我在 D3 AxisControl 类中看到此问题。出于某种原因,它在OnRender方法中做了很多工作,当某些内容发生变化时,它试图通过调用InvalidateVisual来触发该方法。
在问题情况下,问题控件调用 InvalidateVisual,但它们从未收到对 MeasureOverride、ArrangeOverride 或 OnRender 的调用。有趣的是,大多数控件仍然有效,在一个特定问题的情况下,我得到一组 11 个控件中的最后 3 个无法正常工作。值得注意的是,这 3 个(并且只有这 3 个(在触发对 InvalidateVisual 调用的数据绑定更新之前立即收到对 MeasureOverride 的调用。
我的修复
最后,我设法通过添加对InvalidateMeasure的调用以及对InvalidateVisual的调用来修复它。
这是一个可怕的解决方案,但它不是我们应用程序的性能关键部分,所以我似乎侥幸逃脱了。
如果控件的大小保持不变,则不应使用 InvalidateMeasure()
或 InvalidateVisual()
,因为它们会触发昂贵的重新布局。
WPF 是一个保留的绘图系统。 OnRender()
可能更叫AccumulateDrawingObjects()
,因为它实际上并不画。它累积一组绘图对象,WPF 使用这些对象随时绘制 UI。神奇的是,如果您在OnRender()
期间将DrawingGroup
放入DrawingContext
中,您实际上可以在OnRender
后随时有效地更新它。
有关更多详细信息,请参阅我的回答
这里..https://stackoverflow.com/a/44426783/519568
我刚刚也遇到了这个问题。
我有一个用于控件的滚动条,它仅在OnRender()
期间才能弄清楚显示所有内容真正需要多少空间,这可能大于可用的显示空间,因此需要一个滚动条。可能会发生OnRender()
调用一些方法,这些方法最终改变了应该以InvalidateVisual()
开头的滚动条的值OnRender()
。
但是,OnRender()
在InvalidateVisual()
后没有再次接到电话。我想原因是InvalidateVisual()
设置了一些标志,告诉 WPF 需要再次绘制控件,但是一旦OnRender()
完成,该标志就会重置。这里有一些伪代码我期望它发生的方式:
//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;
}
我没有进一步调查 WPF 是否真的以这种方式工作,但它可以解释为什么OnRender()
没有被第二次调用。
我没有浪费更多的时间,而是改变了如何计算控件内容的总宽度,并将此代码放在OnRender()
之外。