In our drag and drop implementation, we like the adorner to apply the adorned element's transform value.
The transform may apply to UIElements in Xaml like this:
<DockPanel.LayoutTransform>
<TransformGroup>
<ScaleTransform ScaleX="0.75" ScaleY="0.75"/>
<RotateTransform Angle="10" />
</TransformGroup>
</DockPanel.LayoutTransform>
<TextBlock>
<TextBlock.LayoutTransform>
...
This is how transforms are retrieved by summarizing the applied transforms of ancestor elements:
public static Transform GetAncestorTransforms(this DependencyObject descendant)
{
TransformGroup transformGroup = new TransformGroup();
DependencyObject dObj = descendant;
do
{
Visual visual = dObj as Visual;
if (visual != null)
{
// determine the current transform by matrix determinants
Transform t = VisualTreeHelper.GetTransform(visual);
if (t != null)
{
transformGroup.Children.Add(t);
}
}
dObj = VisualTreeHelper.GetParent(dObj);
}
while (dObj != null);
return transformGroup;
}
The Adorner draws a round rectangle around the UIElement
protected override void OnRender(DrawingContext drawingContext)
{
var transform = (AdornedItem as DependencyObject).GetAncestorTransforms();
if (transform != null)
{
drawingContext.PushTransform(transform);
}
Rect rect = new Rect(AdornedItem.TranslatePoint(new Point(0, 0), AdornedElement), AdornedItem.RenderSize);
drawingContext.DrawRoundedRectangle(null, new Pen(Foreground, 2), rect, 2, 2);
if (transform != null)
{
drawingContext.Pop();
}
}
The code draws the adorner in the correct size (e.g. if it's a scale transform) or it rotates the adorner into the correct angle (if there's a skew/ rotatetransform) but anyway the rectangle is never around the adorned element. it's somewhere beside it. This looks like an offset problem ?
(Please note that the problem already occurs when theres just a single transform in the wohole visual tree. When there are more transforms, I'm aware that I might swap the order of the summarized transforms in GetAncestorTransforms().)
Found solution: The above code works, except one thing: AdornedItem.TranslatePoint() calculates the starting point for the surrounding rectangle by (already) transformed UIElements. To not apply the transform twice, remove it from the point.