WPF - Shapes vs. DrawingVisual (производительность)
От: CyberSurfer  
Дата: 13.09.13 08:17
Оценка: :)
В MSDN написано:
DrawingVisual is a lightweight drawing class that is used to render shapes, images, or text. This class is considered lightweight because it does not provide layout, input, focus, or event handling, which improves its performance. For this reason, drawings are ideal for backgrounds and clip art.

Я написал код, рисующий тысячу линий с помощью объектов Line, и код, рисующий тысячу линий с помощью объектов DrawingVisual поверх изображения. Сравнивая производительность обоих способов я не увидел никакой разницы. Прокрутка итоговой картинки происходит недостаточно гладко в обоих случаях. Почему лаг при прокрутке итоговой картинки одинаковый в обоих случаях и где производительность класса DrawingVisual?

Первый способ (Line)

<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);
}


Второй способ (DrawingVisual)

<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);
    }
}



13.09.13 15:48: Перенесено модератором из '.NET' — TK
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.