9

自定义 WPF 控件覆盖 OnRender。该方法从自定义数据生成并显示路径。数据提供者使用依赖属性绑定。当数据更改时,依赖属性注册一个事件。该事件依次调用 InvalidateVisual()。

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

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

什么会阻止调用 OnRender 方法?

4

3 回答 3

2

我也刚遇到这个问题。

语境

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

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

在问题案例中,问题控件调用 InvalidateVisual,但它们从未调用过 MeasureOverride、ArrangeOverrideOnRender。有趣的是,大多数控件仍然有效,在一个特定的问题案例中,我得到了一组 11 个无法正常工作的最后 3 个。值得注意的是,这 3 个(并且只有 3 个)在触发 InvalidateVisual 调用的数据绑定更新之前立即收到对 MeasureOverride 的调用。

我的修复

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

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

于 2013-10-14T07:41:39.990 回答
1

如果控件的大小保持不变,则不应使用它们,InvalidateMeasure()或者InvalidateVisual()因为它们会触发昂贵的重新布局。

WPF 是一个保留的绘图系统。OnRender()可能更好地称为AccumulateDrawingObjects(),因为它实际上并没有绘制。它积累了一组绘图对象,WPF 使用这些对象随时绘制您的 UI。神奇的是,如果您将 aDrawingGroup放入DrawingContextduring 中OnRender(),您实际上可以在之后 OnRender随时有效地更新它。

有关更多详细信息,请参见我的答案。

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

于 2017-06-10T07:02:38.190 回答
-1

我也刚遇到这个问题。

我有一个用于控件的滚动条,它只计算OnRender()显示所有内容真正需要多少空间,这可能大于可用的显示空间,因此需要一个滚动条。可能会OnRender()调用一些方法,这些方法最终会改变滚动条的值,而滚动条应该OnRender()InvalidateVisual().

但是,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().

于 2021-07-30T03:34:46.390 回答