2

MSDN 写道:

DrawingVisual 是一个轻量级的绘图类,用于渲染形状、图像或文本。这个类被认为是轻量级的,因为它不提供布局、输入、焦点或事件处理,从而提高了它的性能。出于这个原因,绘图是背景和剪贴画的理想选择。

我编写了一个代码,通过 Line 对象绘制千行,通过 DrawingVisual 对象在图像上绘制千行。比较两种方式的性能我没有看到差异。在任何一种情况下,滚动最终图片都不够流畅。

为什么每种情况下的滚动延迟都相同,而 DrawingVisual 的性能优势在哪里?

第一种方式

<ScrollViewer HorizontalScrollBarVisibility="Auto" 
              VerticalScrollBarVisibility="Auto">
    <Canvas Background="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"
            Name="layoutView">
        <Image>
            <Image.Source>
                <DrawingImage>
                    <DrawingImage.Drawing>
                            <ImageDrawing x:Name="testImage"/>
                    </DrawingImage.Drawing>
                </DrawingImage>
            </Image.Source>
        </Image>
    </Canvas>
</ScrollViewer>

ImageSource imageSource = new BitmapImage(uri);

testImage.Rect = new Rect(
    0, 0, imageSource.Width, imageSource.Height);
testImage.ImageSource = imageSource;

layoutView.Width = imageSource.Width;
layoutView.Height = imageSource.Height;

Random r = new Random();

int max = Math.Min(
    (int)imageSource.Height, (int)imageSource.Width);

for (int i = 0; i < 1000; i++)
{
    Point p1 = new Point(r.Next(max), r.Next(max));
    Point p2 = new Point(r.Next(max), r.Next(max));

    Line line = new Line();
    line.X1 = p1.X;
    line.Y1 = p1.Y;
    line.X2 = p2.X;
    line.Y2 = p2.Y;
    line.Stroke = Brushes.Red;

    layoutView.Children.Add(line);
}

第二种方式

<ScrollViewer HorizontalScrollBarVisibility="Auto" 
              VerticalScrollBarVisibility="Auto">
    <my:VisualView Background="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"
                   x:Name="layoutView">
    </my:VisualView>
</ScrollViewer>

public class VisualView : Canvas
{
    List<Visual> visuals = new List<Visual>();

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

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

    public void AddVisual(Visual visual)
    {
        visuals.Add(visual);
        base.AddVisualChild(visual);
        base.AddLogicalChild(visual);
    }

    public void RemoveVisual(Visual visual)
    {
        visuals.Remove(visual);
        base.RemoveVisualChild(visual);
        base.RemoveLogicalChild(visual);
    }
}

ImageSource imageSource = new BitmapImage(uri);

Random r = new Random();

int max = Math.Min(
    (int)imageSource.Height, (int)imageSource.Width);

DrawingVisual dv = new DrawingVisual();
using (DrawingContext dc = dv.RenderOpen())
{
    dc.DrawImage(imageSource, new Rect(
        0, 0, imageSource.Width, imageSource.Height));
    dc.Close();

    layoutView.AddVisual(dv);

    layoutView.Width = imageSource.Width;
    layoutView.Height = imageSource.Height;
}

Pen pen = new Pen(Brushes.Red, 1);
for (int i = 0; i < 1000; i++)
{
    dv = new DrawingVisual();
    using (DrawingContext dc = dv.RenderOpen())
    {
        Point p1 = new Point(r.Next(max), r.Next(max));
        Point p2 = new Point(r.Next(max), r.Next(max));

        dc.DrawLine(pen, p1, p2);
        dc.Close();

        layoutView.AddVisual(dv);
    }
}
4

1 回答 1

1

您需要仔细测量才能看到真正的差异。可能有一些 WPF ETW 事件可以提供帮助。

如果是这种情况,您将同时拥有图像和矢量图形。如果图像在这里占主导地位,那么任何一种方式都可能非常相似。

尝试先删除图像,看看是否有区别。

使用矢量,您不应该创建 1000 个 DrawingVisual,您可以将 1000 条线绘制成一个 Visual。您甚至可以绘制一条折线。

使用单个折线,您可以通过删除不影响线形状的点来进一步优化。

于 2014-09-15T01:59:18.890 回答