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 various rendering implementations and also because I want to use the power of WPF for a user-friendly interface.
After browsing around for a day, I came across various methods to draw Vector-graphics through WPF.
This guy speaks about different layers within WPF developers can choose from. As I want to use WPF PURELY for his rendering at first, I want to work on the "Visual Layer".
I then came across things like: DrawingVisual, GeometryDrawing, FrameworkElement / UIElement / Shapes
So, I'm a bit overwhelmed by all the different implementations that do eventually the same in totally different ways.
The Graph-Node library has been ported to C# already with all it's logic (including collision detection and dragging with mouse). As it is made with graphic-renderers in mind (like XNA, SlimDX, OpenTK, etc.), what would be the best way in terms of performance to implement a WPF renderer (as in, it will draw whatever the graph library tells it to draw?
Basically, the resulting WPF control acts as a canvas, but it has to be SUPER lightweight and not have any neat WPF features besides providing me a way to draw my circles, lines and other shapes :)
EDIT:
I basically want to know: What is the way to go? Do I extend Canvas as "Host" for my graphics and then add my custom implementation of a UIElement? Or can I have one class which can draw EVERYTHING (as in, one mega super ultra graphic). Much like overriding OnPaint in GDI or Paint-method in Java (which gives a Graphics object to do everything with).
I'd recommend reading Optimizing Performance: 2D Graphics and Imaging (dead link -- readable via Internet Archive) -
Basically,
Drawing
objects will be lighter weight thanShapes
, in general. This is probably what you want to use.the DrawingVisual seems to be a valid choice:
source: Using DrawingVisual Objects
so this seems to be absolutely what you ask, a Canvas SUPER lightweight.
Generally, better performance is obtained with lower-level services. In
WPF
, this means theDrawing
family of objects. All you get are:Drawing
,DrawingGroup
,GeometryDrawing
,GlyphRunDrawing
,ImageDrawing
, andVideoDrawing
. However, they are sufficient for all needs. Using these types is very friendly with WPF becauseDrawing
is the conceptual unit that WPF exchanges with your GPU accelerator, possibly retaining and managing it there if possible. This works because theDrawing
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 onUIElement
,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 fromVisual
--meaning it still requires a hosting element.The following class will host any WPF
Drawing
directly without using an intermediateDrawingVisual
. I added support forFrameworkElement
'sMargin
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.[edit:] This is also useful for inserting a WPF
Drawing
into theInlineUIContainer.Child
property (i.e. usingTextBlock.InlinesCollection
to format the contents of the TextBlock more richly).