I've been wondering how to draw stuff in WPF with a DrawingContext
relative to something that's not the top left corner of the control. My problem is that I want to draw some shapes by connecting various dots, and those dots have to be positionned relative to the center of the host control, with Y pointing upwards.
My elements are rendered using a tree of custom DrawingVisual
subclasses, with the root being a Border
subclass that contains a VisualCollection
. I solved the Y direction problem by specifying a ScaleTransform
as the RenderTransform
of that Border
, essentially flipping the whole control vertically.
No such luck for the other issue, though. Any idea for how to center my origin?
Alright, I got it. Here's how I've done it.
First, I defined a GroupTransform
and assigned to a WorldTransform
property on my Border
subclass.
var trans = new TranslateTransform();
var conv = new HalfConverter(); // a custom converter that halves whatever you pass to it
BindingOperations.SetBinding(trans, TranslateTransform.XProperty, new Binding { Path = new PropertyPath(ActualWidthProperty), Source = this, Converter = conv });
BindingOperations.SetBinding(trans, TranslateTransform.YProperty, new Binding { Path = new PropertyPath(ActualHeightProperty), Source = this, Converter = conv });
WorldTransform = new TransformGroup();
WorldTransform.Children.Add(new ScaleTransform { ScaleY = -1.0 });
WorldTransform.Children.Add(trans);
VisualTransform = WorldTransform;
Then, when I create a new instance of my custom DrawingVisual
, I assign its Transform
property to my WorldTransform
.
// ZoneVisual is my DrawingVisual subclass
var vis = new ZoneVisual(zone) { Transform = WorldTransform };
When I add a new element (a Node
, by the way), I simply need to transform it by the inverse of my WorldTransform
.
Voila. This might not be the best way, but it seems to work pretty well. I don't have remarkably high performance needs, so it will probably do the job.