在Visual Tree中移动UIElement而不重新计算布局

时间:2010-10-19 12:01:39

标签: wpf .net-4.0 visual-tree

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

当然,在Visual Tree中移动内容会重新触发完整的布局。这是有问题的,因为在其中一个停靠窗口中,我们有一个图表控件(Mindfusion Diagramming,WPF控件),可能需要10秒才能完全自行布局(非常大的图表)。

我认为没有直接解决这个问题的方法。我不知道其他有类似问题的程序员是如何解决这个问题的。有没有聪明的方法来避免重新计算布局?

理论上,由于图表在ScrollViewer中,因此真正没有任何变化,因此无论何时放置,可用空间的数量都保持不变(无限)。

编辑:另请注意,内部的图表控件是交互式的。我们需要Drag& Drop。

3 个答案:

答案 0 :(得分:4)

这是一个想法。

  1. 创建一个继承自Decorator的自定义类。
  2. 将图表控件包装在装饰器中。
  3. 覆盖MeasureOverride并简单地调用base.Measure,但在返回之前将结果存储在字段中。
  4. 添加一个属性,可以禁用度量调用。如果属性为true,则只需返回MeasureOverride中的先前大小,而不是调用base.Measure。
  5. 在更改视觉层次结构时设置属性。
  6. 从头脑中,我想不出有什么理由不起作用。

    我实际上在不久前做过非常相似的事情。在NovaMind中为侧面板实现滑动动画时,我使用了一个Decorator来防止内容在面板动画宽度时执行布局。我用最终宽度计算了大小,将其存储起来,然后使用MeasureOverride伪造当前大小...这样可以避免在尝试为复杂控件的宽度设置动画时遇到的性能问题。 :)

答案 1 :(得分:1)

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

我无法使用Actipro对接库本身找到一个优雅的解决方案,所以我想我可以如何转移WPF来做这种行为。我想出的解决方案是使用WinForms UserControl的单个子项将我的内容创建为单个WinFormsHost控件。然后,我让WinForms UserControl让它的内容成为基于WPF的内容,它应该作为停靠窗口内容出现。我想当WPF从树顶开始走视觉树以在树被“剪断”时重新评估所有依赖属性时,它将进入WinForms控件并停止。

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

答案 2 :(得分: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。我可以想象,从长远来看,您可能会为图表创建一个包装类,以便仅在某些内容发生变化(即图表的一部分或大小)时自动显示图像副本并重新布局图表。