MSDN writes:
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.
I wrote a code drawing thousand lines via Line objects and thousand lines via DrawingVisual objects over an image. Comparing performance of both ways I haven't seen a difference. Scrolling a final picture isn't smooth enough in either case.
Why is the lag of scrolling identical in each case and where is the performance benefit of DrawingVisual?
The first way
<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>
and
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);
}
The second way
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<my:VisualView Background="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"
x:Name="layoutView">
</my:VisualView>
</ScrollViewer>
and
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);
}
}
and
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);
}
}
You need to measure carefully to see the real difference. May be there are some WPF ETW events which can help.
If you're case, you have both images and vector graphics. If image is dominating perf here, then either way could be quite similar.
Try to remove images first to see if you see a difference.
With vectors, you should not create 1000 DrawingVisual, you can draw 1000 lines into a single Visual. You can even draw a single polyline.
With a single polyline, you can optimize further by removing points which are not affecting the shape of the line.