Solved it by creating a custom control and instantiating it as child of the adorner some way as microsoft did it with the thumbs in their example.
The custom control then simply creates all the shapes and stuff in the normal way and does not suffer from the problems I faced before.
Here's the code :
public class ResizeableSelectionAdorner : Adorner
{
Thumb topLeft, topRight, bottomLeft, bottomRight;
DrawingSizeIndicator drawingSizeIndicator;
VisualCollection visualChildren;
public ResizeableSelectionAdorner(UIElement adornedElement)
: base(adornedElement)
{
visualChildren = new VisualCollection(this);
BuildAdornerCorner(ref topLeft, Cursors.SizeNWSE);
BuildAdornerCorner(ref topRight, Cursors.SizeNESW);
BuildAdornerCorner(ref bottomLeft, Cursors.SizeNESW);
BuildAdornerCorner(ref bottomRight, Cursors.SizeNWSE);
bottomLeft.DragDelta += new DragDeltaEventHandler(HandleBottomLeft);
bottomRight.DragDelta += new DragDeltaEventHandler(HandleBottomRight);
topLeft.DragDelta += new DragDeltaEventHandler(HandleTopLeft);
topRight.DragDelta += new DragDeltaEventHandler(HandleTopRight);
bottomLeft.GotMouseCapture += new MouseEventHandler(Corner_GotMouseCapture);
bottomRight.GotMouseCapture += new MouseEventHandler(Corner_GotMouseCapture);
topLeft.GotMouseCapture += new MouseEventHandler(Corner_GotMouseCapture);
topRight.GotMouseCapture += new MouseEventHandler(Corner_GotMouseCapture);
bottomLeft.LostMouseCapture += new MouseEventHandler(Corner_LostMouseCapture);
bottomRight.LostMouseCapture += new MouseEventHandler(Corner_LostMouseCapture);
topLeft.LostMouseCapture += new MouseEventHandler(Corner_LostMouseCapture);
topRight.LostMouseCapture += new MouseEventHandler(Corner_LostMouseCapture);
drawingSizeIndicator = new DrawingSizeIndicator();
drawingSizeIndicator.Opacity = 0;
visualChildren.Add(drawingSizeIndicator);
}
void Corner_LostMouseCapture(object sender, MouseEventArgs e)
{
bottomLeft.Opacity = 0.4;
bottomRight.Opacity = 0.4;
topLeft.Opacity = 0.4;
topRight.Opacity = 0.4;
drawingSizeIndicator.Opacity = 0;
InvalidateVisual();
}
void Corner_GotMouseCapture(object sender, MouseEventArgs e)
{
bottomLeft.Opacity = 0;
bottomRight.Opacity = 0;
topLeft.Opacity = 0;
topRight.Opacity = 0;
drawingSizeIndicator.Opacity = 1;
InvalidateVisual();
}
void HandleBottomRight(object sender, DragDeltaEventArgs args)
{
FrameworkElement adornedElement = this.AdornedElement as FrameworkElement;
Thumb hitThumb = sender as Thumb;
if (adornedElement == null || hitThumb == null) return;
FrameworkElement parentElement = adornedElement.Parent as FrameworkElement;
EnforceSize(adornedElement);
adornedElement.Width = Math.Max(adornedElement.Width + args.HorizontalChange, hitThumb.DesiredSize.Width);
adornedElement.Height = Math.Max(args.VerticalChange + adornedElement.Height, hitThumb.DesiredSize.Height);
}
void HandleBottomLeft(object sender, DragDeltaEventArgs args)
{
FrameworkElement adornedElement = AdornedElement as FrameworkElement;
Thumb hitThumb = sender as Thumb;
if (adornedElement == null || hitThumb == null) return;
EnforceSize(adornedElement);
if (adornedElement.Width != Math.Max(adornedElement.Width - args.HorizontalChange, hitThumb.DesiredSize.Width))
{
double x = Canvas.GetLeft(adornedElement) + args.HorizontalChange;
Canvas.SetLeft(adornedElement, x);
adornedElement.Width = Math.Max(adornedElement.Width - args.HorizontalChange, hitThumb.DesiredSize.Width);
}
adornedElement.Height = Math.Max(args.VerticalChange + adornedElement.Height, hitThumb.DesiredSize.Height);
}
void HandleTopRight(object sender, DragDeltaEventArgs args)
{
FrameworkElement adornedElement = this.AdornedElement as FrameworkElement;
Thumb hitThumb = sender as Thumb;
if (adornedElement == null || hitThumb == null) return;
FrameworkElement parentElement = adornedElement.Parent as FrameworkElement;
EnforceSize(adornedElement);
adornedElement.Width = Math.Max(adornedElement.Width + args.HorizontalChange, hitThumb.DesiredSize.Width);
double y = Canvas.GetTop(adornedElement) + args.VerticalChange;
Canvas.SetTop(adornedElement, y);
adornedElement.Height = Math.Max(adornedElement.Height - args.VerticalChange, hitThumb.DesiredSize.Height);
}
void HandleTopLeft(object sender, DragDeltaEventArgs args)
{
FrameworkElement adornedElement = AdornedElement as FrameworkElement;
Thumb hitThumb = sender as Thumb;
if (adornedElement == null || hitThumb == null) return;
EnforceSize(adornedElement);
if (adornedElement.Width != Math.Max(adornedElement.Width - args.HorizontalChange, hitThumb.DesiredSize.Width))
{
double x = Canvas.GetLeft(adornedElement) + args.HorizontalChange;
Canvas.SetLeft(adornedElement, x);
adornedElement.Width = Math.Max(adornedElement.Width - args.HorizontalChange, hitThumb.DesiredSize.Width);
}
if (adornedElement.Height != Math.Max(adornedElement.Height - args.VerticalChange, hitThumb.DesiredSize.Height))
{
double y = Canvas.GetTop(adornedElement) + args.VerticalChange;
Canvas.SetTop(adornedElement, y);
adornedElement.Height = Math.Max(adornedElement.Height - args.VerticalChange, hitThumb.DesiredSize.Height);
}
}
protected override Size ArrangeOverride(Size finalSize)
{
double desiredWidth = ActualWidth;
double desiredHeight = ActualHeight;
double adornerWidth = this.DesiredSize.Width;
double adornerHeight = this.DesiredSize.Height;
topLeft.Arrange(new Rect(-adornerWidth / 2, -adornerHeight / 2, adornerWidth, adornerHeight));
topRight.Arrange(new Rect(desiredWidth - adornerWidth / 2, -adornerHeight / 2, adornerWidth, adornerHeight));
bottomLeft.Arrange(new Rect(-adornerWidth / 2, desiredHeight - adornerHeight / 2, adornerWidth, adornerHeight));
bottomRight.Arrange(new Rect(desiredWidth - adornerWidth / 2, desiredHeight - adornerHeight / 2, adornerWidth, adornerHeight));
drawingSizeIndicator.Arrange(new Rect(-drawingSizeIndicator.ElementIndicatorLength+1,-drawingSizeIndicator.ElementIndicatorLength,
desiredWidth + drawingSizeIndicator.ElementIndicatorLength * 4 + drawingSizeIndicator.SizeIndicatorLength-2,
desiredHeight + drawingSizeIndicator.ElementIndicatorLength * 4 + drawingSizeIndicator.SizeIndicatorLength-1));
return finalSize;
}
void BuildAdornerCorner(ref Thumb cornerThumb, Cursor customizedCursor)
{
if (cornerThumb != null) return;
cornerThumb = new Thumb();
cornerThumb.Cursor = customizedCursor;
cornerThumb.Height = cornerThumb.Width = 10;
cornerThumb.Opacity = 0.40;
cornerThumb.Background = new SolidColorBrush(Colors.MediumBlue);
visualChildren.Add(cornerThumb);
}
void EnforceSize(FrameworkElement adornedElement)
{
if (adornedElement.Width.Equals(Double.NaN))
adornedElement.Width = adornedElement.DesiredSize.Width;
if (adornedElement.Height.Equals(Double.NaN))
adornedElement.Height = adornedElement.DesiredSize.Height;
FrameworkElement parent = adornedElement.Parent as FrameworkElement;
if (parent != null)
{
adornedElement.MaxHeight = parent.ActualHeight;
adornedElement.MaxWidth = parent.ActualWidth;
}
}
protected override int VisualChildrenCount { get { return visualChildren.Count; } }
protected override Visual GetVisualChild(int index) { return visualChildren[index]; }
}