Custom DrawingVisual制作应用程序缓慢

时间:2014-03-01 16:09:06

标签: wpf curve drawingvisual

我想渲染一条包含数百个点的贝塞尔曲线。这条曲线不需要以任何方式进行测试或可交互,因此我认为我会尝试使用Visual,因为它似乎是最轻量级的。

虽然使用下面的代码,为什么导致应用程序的其余部分运行缓慢?例如,窗口大小调整非常慢。

我只是在寻找最有效的方式来渲染曲线而没有任何输入处理功能(即使使用这个例子,你可以连接到MouseOver事件,它只会在光标实际上在线上时触发,所以看起来我仍在付钱(设置IsHitTestVisiable似乎对性能没有帮助))

public class VisualHost : FrameworkElement
{
    VisualCollection _children;

    public VisualHost()
    {
        _children = new VisualCollection(this);
        _children.Add(CreateDrawingVisualRectangle());

    }

    DrawingVisual CreateDrawingVisualRectangle()
    {
        var drawingVisual = new DrawingVisual();
        var drawingContext = drawingVisual.RenderOpen();

        var geometry = new StreamGeometry();
        using (var ctx = geometry.Open())
        {
            ctx.BeginFigure(new Point(0, 0), false, false);
            var r = new Random();

            for (int i = 0; i < 500; ++i)
            {
                var p1 = new Point(r.Next(0, 1000), r.Next(0, 1000));
                var p2 = new Point(r.Next(0, 1000), r.Next(0, 1000));
                ctx.QuadraticBezierTo(p1, p2, true, false);
            }
        }

        geometry.Freeze();

        drawingContext.DrawGeometry(null, new Pen(Brushes.Red, 1), geometry);
        drawingContext.Close();

        return drawingVisual;
    }

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

    protected override Visual GetVisualChild(int index)
    {
        if (index < 0 || index >= _children.Count)
        {
            throw new ArgumentOutOfRangeException();
        }

        return _children[index];
    }
}

public partial class MainWindow : Window
{
    public MainWindow()
    {
        Content = new VisualHost();
    }
}

1 个答案:

答案 0 :(得分:2)

您可以使用BitmapCache创建一个位图来缓存DrawingVisual的呈现...以便当FrameworkElement无效时(由于大小调整)缓存的位图用于提供&#34;视觉位&#34;而不是必须在&#34; DrawingVisual&#34;内绘制绘图指令的较慢路径。再次(即绘图上下文中由StreamGeometry描述的内容)。

   DrawingVisual CreateDrawingVisualRectangle()
    {
        var drawingVisual = new DrawingVisual();
        var drawingContext = drawingVisual.RenderOpen();

        var geometry = new StreamGeometry();
        using (var ctx = geometry.Open())
        {
            ctx.BeginFigure(new Point(0, 0), false, false);
            var r = new Random();

            for (int i = 0; i < 500; ++i)
            {
                var p1 = new Point(r.Next(0, 1000), r.Next(0, 1000));
                var p2 = new Point(r.Next(0, 1000), r.Next(0, 1000));
                ctx.QuadraticBezierTo(p1, p2, true, false);
            }
        }

        geometry.Freeze();

        drawingContext.DrawGeometry(null, new Pen(Brushes.Red, 1), geometry);
        drawingContext.Close();

        drawingVisual.CacheMode = new BitmapCache();

        return drawingVisual;
    }