I am creating a tool which relies heavily on graph-node trees. The current implementation is done in Java and I\'m porting it to a generic code-base on C#, so it can be used by
I'd recommend reading Optimizing Performance: 2D Graphics and Imaging (dead link -- readable via Internet Archive) -
Basically, Drawing
objects will be lighter weight than Shapes
, in general. This is probably what you want to use.
Generally, better performance is obtained with lower-level services. In WPF
, this means the Drawing
family of objects. All you get are: Drawing
, DrawingGroup
, GeometryDrawing
, GlyphRunDrawing
, ImageDrawing
, and VideoDrawing
. However, they are sufficient for all needs. Using these types is very friendly with WPF because Drawing
is the conceptual unit that WPF exchanges with your GPU accelerator, possibly retaining and managing it there if possible. This works because the Drawing
is expressed in terms of portable vector drawing primitives.
Once you start re-architecting your app around Drawings
however, you might need some interop with your higher-level code which is still based on UIElement
, FrameworkElement
, etc. One thing that I haven't found built-in to WPF is a simple way to wrap a Drawing as a FrameworkElement in the lowest-overhead way possible. DrawingVisual
isn't a complete solution, because it only derives from Visual
--meaning it still requires a hosting element.
The following class will host any WPF Drawing
directly without using an intermediate DrawingVisual
. I added support for FrameworkElement
's Margin
property (with no performance penalty if unused) but little else. Because of WPF's single rendering thread it's safe and easy to cache a single TranslateTransform object to implement the margin. I'd recommend that you supply only drawings which have been Frozen; in fact, in the version that I use, I have an assert to that effect in the constructor.
public class DrawingElement : FrameworkElement
{
static readonly TranslateTransform tt_cache = new TranslateTransform();
public DrawingElement(Drawing drawing)
{
this.drawing = drawing;
}
readonly Drawing drawing;
TranslateTransform get_transform()
{
if (Margin.Left == 0 && Margin.Top == 0)
return null;
tt_cache.X = Margin.Left;
tt_cache.Y = Margin.Top;
return tt_cache;
}
protected override Size MeasureOverride(Size _)
{
var sz = drawing.Bounds.Size;
return new Size
{
Width = sz.Width + Margin.Left + Margin.Right,
Height = sz.Height + Margin.Top + Margin.Bottom,
};
}
protected override void OnRender(DrawingContext dc)
{
var tt = get_transform();
if (tt != null)
dc.PushTransform(tt);
dc.DrawDrawing(drawing);
if (tt != null)
dc.Pop();
}
};
[edit:] This is also useful for inserting a WPF Drawing
into the InlineUIContainer.Child
property (i.e. using TextBlock.InlinesCollection
to format the contents of the TextBlock more richly).
the DrawingVisual seems to be a valid choice:
The 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 or event handling, which improves its performance. For this reason, drawings are ideal for backgrounds and clip art.
source: Using DrawingVisual Objects
so this seems to be absolutely what you ask, a Canvas SUPER lightweight.