/// <summary> /// Occurs as the mouse changes position when a Thumb control has logical focus and mouse capture /// </summary> /// <param name="sender">The sender</param> /// <param name="e">The event args</param> private void ResizeDragDelta(object sender, DragDeltaEventArgs e) { // get to resized element Grid thumbsGrid = (Grid)VisualTreeHelper.GetParent(this); Thumb parentThumb = (Thumb)VisualTreeHelper.GetParent(thumbsGrid); Adorner adorner = (Adorner)VisualTreeHelper.GetParent(parentThumb); // presenter that holds dragged item ContentPresenter presenter = (ContentPresenter) VisualTreeHelper.GetParent(adorner.AdornedElement); // parent canvas CustomCanvas canvas = (CustomCanvas) VisualTreeHelper.GetParent(presenter); // prepare items for resize depending on item level (question or bubble) List<ContentPresenter> presenters; if (canvas.Name.Equals(Properties.Resources.RootCanvasName)) { // here we resize questions (e.g. choicebox), so take selected items presenters = ControlHelper.GetSelectedChildPresenters(canvas); } else { // here we resize bubbles, so get neighbor bubbles inside question (always resize bubbles equally) presenters = ControlHelper.GetChildPresenters(canvas); } double minLeft, minTop, minDeltaHorizontal, minDeltaVertical; double maxDeltaVertical, maxDeltaHorizontal; double maxHorizontalDeltaToChild = double.MaxValue; double maxVerticalDeltaToChild = double.MaxValue; this.CalculateLimits(canvas, presenters, out minLeft, out minTop, out minDeltaHorizontal, out minDeltaVertical, out maxDeltaHorizontal, out maxDeltaVertical); minDeltaVertical = Math.Min(minDeltaVertical, maxVerticalDeltaToChild); minDeltaHorizontal = Math.Min(minDeltaHorizontal, maxHorizontalDeltaToChild); foreach (ContentPresenter element in presenters) { double newHeight = element.ActualHeight; double newWidth = element.ActualWidth; double newTop = Canvas.GetTop(element); double newLeft = Canvas.GetLeft(element); double scale, dragDeltaVertical; switch (this.VerticalAlignment) { case VerticalAlignment.Bottom: dragDeltaVertical = Math.Max(Math.Min(-e.VerticalChange, minDeltaVertical), -maxDeltaVertical); newHeight = element.ActualHeight - dragDeltaVertical; break; case VerticalAlignment.Top: dragDeltaVertical = Math.Min(Math.Max(-minTop, e.VerticalChange), minDeltaVertical); scale = (element.ActualHeight - dragDeltaVertical) / element.ActualHeight; newTop = newTop - element.Height * (scale - 1); newHeight = element.ActualHeight - dragDeltaVertical; break; } double dragDeltaHorizontal; switch (this.HorizontalAlignment) { case HorizontalAlignment.Left: dragDeltaHorizontal = Math.Min(Math.Max(-minLeft, e.HorizontalChange), minDeltaHorizontal); scale = (element.ActualWidth - dragDeltaHorizontal) / element.ActualWidth; newLeft = Canvas.GetLeft(element) - element.Width * (scale - 1); newWidth = element.ActualWidth * scale; break; case HorizontalAlignment.Right: dragDeltaHorizontal = Math.Max(Math.Min(-e.HorizontalChange, minDeltaHorizontal), -maxDeltaHorizontal); newWidth = element.ActualWidth - dragDeltaHorizontal; break; } var childs = this.GetChildElements(element); if (childs == null) { element.Width = newWidth; element.Height = newHeight; Canvas.SetTop(element, newTop); Canvas.SetLeft(element, newLeft); } else { double scaleH = newHeight / element.ActualHeight; double scaleW = newWidth / element.ActualWidth; if (this.CanTransformChildsRecursive(childs, scaleH, scaleW)) { this.TransformChildsRecursive(childs, scaleH, scaleW); element.Width = newWidth; element.Height = newHeight; Canvas.SetTop(element, newTop); Canvas.SetLeft(element, newLeft); } } } e.Handled = true; }