2

我们有一个使用停靠控件(Actipro)的 WPF 应用程序(.Net 4.0)。我们可以停靠停靠窗口。在这种情况下,将创建一个“真实”窗口并将内容分配给该窗口。

当然,在可视化树中移动东西会重新触发完整的布局。这是有问题的,因为在这些停靠窗口之一中,我们有一个图表控件(Mindfusion Diagramming,WPF 控件),它可能需要长达 10 秒才能完全布局自身(非常大的图表)。

我认为这个问题没有任何直接的解决方案。然而,我想知道其他有类似问题的程序员是如何解决这个问题的。有什么巧妙的方法可以避免重新计算布局吗?

理论上,由于图表位于 ScrollViewer 内部,因此没有任何实际变化,因此无论何时放置它,可用空间量都保持不变(无限)。

编辑:还要注意里面的图表控件是交互式的。我们需要拖放。

4

3 回答 3

4

这是一个想法。

  1. 创建一个继承自 Decorator 的自定义类。
  2. 将您的图表控件包装在装饰器中。
  3. 覆盖 MeasureOverride 并简单地调用 base.Measure 但在返回之前将结果存储在一个字段中。
  4. 添加一个属性,使您能够禁用测量调用。如果该属性为真,只需在 MeasureOverride 中返回之前的大小,而不是调用 base.Measure。
  5. 在更改视觉层次结构时设置属性。

从我的脑海中,我想不出任何为什么这不起作用的原因。

不久前,我实际上做了一些非常相似的事情。在NovaMind中实现侧面板的滑动动画时,我使用了装饰器来防止内容在面板为其宽度设置动画时执行布局。我用最终宽度计算大小,存储它,然后使用 MeasureOverride 来伪造当前大小......这防止了在尝试为复杂控件的宽度设置动画时涉及的性能问题。:)

于 2010-10-28T01:48:29.167 回答
1

另一种可能性是,当将内容从一个窗口移动到另一个窗口时,问题与布局无关,而是与视觉树的“切断”有关。这似乎会导致依赖属性的大量重新计算,如果你的内容可视化树像我的一样,超过 2000 个控件,它真的很慢。

我找不到使用 Actipro 对接库本身的优雅解决方案,所以我想我可以如何转移 WPF 的这种行为。我想出的解决方案是将我的内容创建为带有 WinForms UserControl 的单个子项的单个 WinFormsHost 控件。然后,我使 WinForms UserControl 的内容成为应该显示为停靠窗口内容的基于 WPF 的内容。我想当 WPF 开始从顶部遍历可视化树以重新评估所有依赖属性时,当树被“剪断”时,它会遇到 WinForms 控件并停止。

我的 Actipro 对接工具窗口过去需要 6 秒左右才能切换标签或浮动。现在它们基本上是瞬时的。您必须确保任何命令处理程序都不是在应用程序级别,而是在您的 WPF 内容级别,并且您可能必须使用某些样式文件的位置来解决问题,但它工作得非常好。

于 2013-01-28T15:12:55.063 回答
0

您可能希望用图像替换可视树中的图表控件,在屏幕外渲染图表并使用 rendertargetbitmap 将渲染的图表转换为图像,您可以将其用作可视树中图像的源。

像这样的东西:

// image is the Image from the visual tree
int h = image.ActualHeight;
int w = image.ActualWidth;

// layout the diagram to the size of the image
diagram.Measure(new Size(w, h));
diagram.Arrange(new Rect(newSize(w,h)));
diagram.UpdateLayout();

// render the diagram to a bitmap
RenderTargetBitmap bmp = new RenderTargetBitmap((int)w, (int)h, 96, 96, PixelFormats.Default);
bmp.Render(diagram);

// set the source of your image to the bitmap
image.Source = bmp;

在示例中,如果 PixelFormats.Default 似乎不起作用,您可以尝试 PixelFormats.Pbgra32,我认为这是在这种类型的事情中使用的更常见的格式。

您也可以以类似的方式使用 VisualBrush。我可以想象,从长远来看,您可能会为图表创建一个包装类,以自动显示图像副本并仅在某些情况发生变化时重新布局图表(即图表的一部分或大小)。

于 2010-10-19T17:05:59.060 回答