提高绘制视觉渲染的速度

时间:2009-11-18 11:59:44

标签: wpf performance

我创建了自己的FrameworkElement并通过返回我自己的DrawingVisual集合实例来覆盖VisualChildrenCount {get;}和GetVisualChild(int index)。我有覆盖OnRender。

我将在此FrameworkElement中添加20-50个DrawingVisuals,每个DrawingVisual将有2000个线段。这些点的逻辑值介于0到60000之间。当我放大1:1时,FrameworkElement的高度将为60000,退役时间为15分钟!!

如何提高撕裂性能?

2 个答案:

答案 0 :(得分:4)

对于这种数据量,我建议您为每个点构建一个包含单个PolyLine的GeometryDrawing和StreamGeometry。然后将它们组合在一个DrawingGroup中,并使用一个DrawingVisual显示它。

这将是XAML:

<DrawingVisual Drawing="{Binding CurrentDrawing}" />

这将是更新CurrentDrawing的代码:

var group = new DrawingGroup();
foreach(var data in myData)
{
  StreamGeometry geo = new StreamGeometry();
  using(geoContext = geo.Open())
  {
    geoContext.BeginFigure(myData.StartPoint, false, false);
    geoContext.PolyLineTo(myData.AdditionalPoints, true, false);
  }
  group.Add(new GeometryDrawing
  {
    Geometry = geo,
    Pen = myData.Pen,
  });
}
CurrentDrawing = group;
...

如果你的数据正在改变,那么分别创建存储每个GeometryDrawing对象可能是有利的,因此只需要重新创建那些源数据已经改变的GeometryDrawings。

<强>更新

您在评论中提到需要单独测试每个20-50个数据项。在这种情况下,您可能希望为每个使用单独的DrawingVisual。为了获得最佳性能,您需要将RenderOpen()DrawingContext

一起使用
IEnumerable<Visual> BuildVisuals()
{
  return
    from var data in myData
    select BuildVisualForData(data);
}

void BuildVisualForData(MyDataType data)
{
  var geo = new StreamGeometry();
  using(geoContext = geo.Open())
  {
    geoContext.BeginFigure(myData.StartPoint, false, false);
    geoContext.PolyLineTo(myData.AdditionalPoints, true, false);
  }

  var visual = new DrawingVisual();
  using(drawingContext = visual.RenderOpen())
  {
    drawingContext.DrawGeometry(null, myData.Pen, geo);
  }
  return visual;
}

答案 1 :(得分:0)

我需要使用hittesting来突出每个视觉效果。如果我使用单个DrawingVisual显示它们,我认为它可能没有完成。

对于这种数据量,我建议您为每个点构建一个包含单个PolyLine的GeometryDrawing和StreamGeometry。然后将它们组合在一个DrawingGroup中,并使用一个DrawingVisual显示它。

这将是XAML:

<DrawingVisual Drawing="{Binding CurrentDrawing}" />

这将是更新CurrentDrawing的代码:

var group = new DrawingGroup();
foreach(var data in myData)
{
  StreamGeometry geo = new StreamGeometry();
  using(geoContext = geo.Open())
  {
    geoContext.BeginFigure(myData.StartPoint, false, false);
    geoContext.PolyLineTo(myData.AdditionalPoints, true, false);
  }
  group.Add(new GeometryDrawing
  {
    Geometry = geo,
    Pen = myData.Pen,
  });
}
CurrentDrawing = group;
...

如果你的数据正在改变,那么分别创建存储每个GeometryDrawing对象可能是有利的,所以只需要重新创建源数据已经改变的GeometryDrawings