WPF C#中的StreamGeometry与DrawingContext.DrawLine有何区别?

6

我将实时绘制数百条线。我选择使用Visual Layer进行操作。但是我发现这里有两种不同的绘制线条方式。您建议使用哪一种以获得更好的性能和速度?

1. DrawingContext.DrawLine

public class DrawingTypeOne : FrameworkElement
{
    private readonly VisualCollection _visuals;
    public DrawingTypeOne(double thickness)
    {
        var myPen = new Pen
        {
            Thickness = 1,
            Brush = Brushes.White,
        };
        myPen.Freeze();

        _visuals = new VisualCollection(this);
        var drawingVisual = new DrawingVisual();
        using (var dc = drawingVisual.RenderOpen())
        {
            dc.DrawLine(myPen, new Point(0,0) , new Point(100,100));
            _visuals.Add(drawingVisual);
        }
    }

    protected override Visual GetVisualChild(int index)
    {
        return _visuals[index];
    }

    protected override int VisualChildrenCount
    {
        get
        {
            return _visuals.Count;
        }
    }
}

2. StreamGeometry

public class DrawingTypeTwo : FrameworkElement
{
    private readonly VisualCollection _visuals;
    public DrawingTypeTwo()
    {
        _visuals = new VisualCollection(this);

        var geometry = new StreamGeometry();
        using (var gc = geometry.Open())
        {
            gc.BeginFigure(new Point(0, 0), true, true);
            gc.LineTo(new Point(100,100), true, false);
        }
        geometry.Freeze();

        var drawingVisual = new DrawingVisual();
        using (var dc = drawingVisual.RenderOpen())
        {
            dc.DrawGeometry(Brushes.Red, null, geometry);
        }

        _visuals.Add(drawingVisual);
    }

    protected override Visual GetVisualChild(int index)
    {
        return _visuals[index];
    }

    protected override int VisualChildrenCount
    {
        get
        {
            return _visuals.Count;
        }
    }
}

7
为什么不试试两者,自己回答自己的问题呢? - Reed Copsey
1
@Vahid 是的,理论上来说,它比路径信息更轻量级,因为它不支持一些相同的功能集。 - Reed Copsey
1
第一种方法更快。 - dev hedgehog
1
因为第二种方法最终做的与第一种方法相同,只是包装得更好。DrawLine是最底层的。你不能比DrawLine更深入了。DrawGeometry调用DrawLine和其他一些内部内容。 - dev hedgehog
2
如果你想要更好的性能,请不要为100行创建100个可视元素,而是创建一个可视元素并在其中绘制这100行。WPF会缓存您的绘画,因此您不需要从FrameworkElement继承。此外,这也是如何创建一个没有测量和排列支持的可视元素,并且可以节省大量时间。 - dev hedgehog
显示剩余17条评论
1个回答

4

就像我说的,你只需要一个视觉元素,然后在里面添加所有的线条。

看一下这个:

首先,在我们的绘图环境中定义多个图形:

class EllipseAndRectangle : DrawingVisual
{
    public EllipseAndRectangle()
    {
        using (DrawingContext dc = RenderOpen())
        {
            // Black ellipse with blue border
            dc.DrawEllipse(Brushes.Black,
                new Pen(Brushes.Blue, 3),        
                new Point(120, 120), 20, 40); 

            // Red rectangle with green border
            dc.DrawRectangle(Brushes.Red,
                new Pen(Brushes.Green, 4),    
                new Rect(new Point(10, 10), new Point(80, 80))); 
        }
    }
}

这是一个特殊的视觉元素,用于承载所有绘图内容:

public class EllAndRectHost : FrameworkElement
{
    private EllipseAndRectangle _ellAndRect = new EllipseAndRectangle();

    // EllipseAndRectangle instance is our only visual child
    protected override Visual GetVisualChild(int index)
    {
        return _ellAndRect;
    }

    protected override int VisualChildrenCount
    {
        get
        {
            return 1;
        }
    }
}

以下是如何在XAML中使用这些东西的方法:

<local:EllAndRectHost Margin="30" ... />

我谈论的是 DrawingVisual 类,您可以从中继承而不是为 100 条线创建 100 个可视化对象。
关于您的问题,第一种方法更快。因为第二种方法最终做的与第一种方法相同,只是进行了优化。DrawLine 是最底层的,您不能再进一步深入了。DrawGeometry 调用 DrawLine 和其他一些内部操作。

1
实际上我正在按照上述方式进行。我的循环在Using内运行。如果不继承FrameworkElement怎么办?我读到可以继承UIElement - Vahid
1
在你的代码中,有这一行:_visuals.Add(drawingVisual); 我觉得你是将每一行添加到 VisualCollection 中。然后你可以使用 _visuals[index]; 访问它们。没有必要拥有 100 个 DrawingVisuals,只需要一个就可以了。 :) - dev hedgehog
2
是的,你可以从UIElement甚至Visual继承。你所需要的只是一个具备所有绘图元素的主机和视觉元素。Grid、StackPanel和Canvas都可以作为你的主机。在WPF中,所有东西都是Visual。 - dev hedgehog
你能否在你的回答中附上关于StreamGeometry的评论?我已经接受了这个答案,我希望它与问题相关。 - Vahid
5
始终将自己视为专业人士,不要声称这是一个错误,而要将其作为特性来销售。 - dev hedgehog
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接