I am currently working on a C # WPF application that contains a full screen Gridwith controls that are dynamically added to it at runtime. I have code that allows the user to move these controls through Gridwith mouse events. Now I want the user to also resize the controls (while maintaining the aspect ratio), also at runtime. I have seen various tutorials describing how to do this using controls Canvas(and Thumb), but none of them are Grid. Since I cannot use Canvasin my application, is there an efficient way to implement this on a grid? To give you an idea of ββwhat my code looks like, I have placed the mouse events below: [Edited below]
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
public static Point _anchorPoint;
public static Point _currentPoint;
private static double _originalTop;
private static double _originalLeft;
private static Point _startPoint;
private static bool _isDown = false;
private static bool _isInDrag = false;
private static bool _isDragging = false;
public static UIElement selectedElement = null;
public static bool elementIsSelected = false;
public static Dictionary<object, TranslateTransform> PointDict = new Dictionary<object, TranslateTransform>();
public static AdornerLayer aLayer;
public MainWindow()
{
InitializeComponent();
}
public static void Control_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (_isInDrag)
{
var element = sender as FrameworkElement;
element.ReleaseMouseCapture();
_isInDrag = false;
e.Handled = true;
aLayer = AdornerLayer.GetAdornerLayer(selectedElement);
aLayer.Add(new ResizingAdorner(selectedElement));
}
}
public static void HUD_MouseDown(object sender, MouseButtonEventArgs e)
{
if (elementIsSelected)
{
elementIsSelected = false;
_isDown = false;
if (selectedElement != null)
{
aLayer.Remove(aLayer.GetAdorners(selectedElement)[0]);
selectedElement = null;
}
}
if (e.Source != mw.PACSGrid)
{
_isDown = true;
_startPoint = e.GetPosition(mw.PACSGrid);
selectedElement = e.Source as UIElement;
_originalLeft = VisualWorker.GetLeft(selectedElement);
_originalTop = VisualWorker.GetTop(selectedElement);
aLayer = AdornerLayer.GetAdornerLayer(selectedElement);
aLayer.Add(new ResizingAdorner(selectedElement));
elementIsSelected = true;
e.Handled = true;
}
}
public static void Control_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (elementIsSelected)
{
aLayer.Remove(aLayer.GetAdorners(selectedElement)[0]);
selectedElement = sender as UIElement;
var element = sender as FrameworkElement;
_anchorPoint = e.GetPosition(null);
element.CaptureMouse();
_isInDrag = true;
e.Handled = true;
}
}
public static void Control_MouseMove(object sender, MouseEventArgs e)
{
if (_isInDrag)
{
_currentPoint = e.GetPosition(null);
TranslateTransform tt = new TranslateTransform();
bool isMoved = false;
if (PointDict.ContainsKey(sender))
{
tt = PointDict[sender];
isMoved = true;
}
tt.X += _currentPoint.X - _anchorPoint.X;
tt.Y += (_currentPoint.Y - _anchorPoint.Y);
_anchorPoint = _currentPoint;
(sender as UIElement).RenderTransform = tt;
if (isMoved)
{
PointDict.Remove(sender);
}
PointDict.Add(sender, tt);
}
}
}
public class ResizingAdorner : Adorner
{
Thumb topLeft, topRight, bottomLeft, bottomRight;
VisualCollection visualChildren;
public ResizingAdorner(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);
}
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 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 height_old = adornedElement.Height;
double height_new = Math.Max(adornedElement.Height - args.VerticalChange, hitThumb.DesiredSize.Height);
double top_old = VisualWorker.GetTop(adornedElement);
adornedElement.Height = height_new;
VisualWorker.SetTop(adornedElement, top_old - (height_new - height_old));
}
void HandleTopLeft(object sender, DragDeltaEventArgs args)
{
FrameworkElement adornedElement = AdornedElement as FrameworkElement;
Thumb hitThumb = sender as Thumb;
if (adornedElement == null || hitThumb == null) return;
EnforceSize(adornedElement);
double width_old = adornedElement.Width;
double width_new = Math.Max(adornedElement.Width - args.HorizontalChange, hitThumb.DesiredSize.Width);
double left_old = VisualWorker.GetLeft(adornedElement);
adornedElement.Width = width_new;
VisualWorker.SetLeft(adornedElement, left_old - (width_new - width_old));
double height_old = adornedElement.Height;
double height_new = Math.Max(adornedElement.Height - args.VerticalChange, hitThumb.DesiredSize.Height);
double top_old = VisualWorker.GetTop(adornedElement);
adornedElement.Height = height_new;
VisualWorker.SetTop(adornedElement, top_old - (height_new - height_old));
}
void HandleBottomLeft(object sender, DragDeltaEventArgs args)
{
FrameworkElement adornedElement = AdornedElement as FrameworkElement;
Thumb hitThumb = sender as Thumb;
if (adornedElement == null || hitThumb == null) return;
EnforceSize(adornedElement);
adornedElement.Height = Math.Max(args.VerticalChange + adornedElement.Height, hitThumb.DesiredSize.Height);
double width_old = adornedElement.Width;
double width_new = Math.Max(adornedElement.Width - args.HorizontalChange, hitThumb.DesiredSize.Width);
double left_old = VisualWorker.GetLeft(adornedElement);
adornedElement.Width = width_new;
VisualWorker.SetLeft(adornedElement, left_old - (width_new - width_old));
}
protected override Size ArrangeOverride(Size finalSize)
{
double desiredWidth = AdornedElement.DesiredSize.Width;
double desiredHeight = AdornedElement.DesiredSize.Height;
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));
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 = 1;
cornerThumb.Background = new ImageBrush(new BitmapImage(new Uri(@"pack://application:,,,/Images/Thumb 1.jpg")));
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]; }
}
public class VisualWorker
{
public static void SetTop(UIElement uie, double top)
{
var frame = uie as FrameworkElement;
frame.Margin = new Thickness(frame.Margin.Left, top, frame.Margin.Right, frame.Margin.Bottom);
}
public static void SetLeft(UIElement uie, double left)
{
var frame = uie as FrameworkElement;
frame.Margin = new Thickness(left, frame.Margin.Top, frame.Margin.Right, frame.Margin.Bottom);
}
public static double GetTop(UIElement uie)
{
return (uie as FrameworkElement).Margin.Top;
}
public static double GetLeft(UIElement uie)
{
return (uie as FrameworkElement).Margin.Left;
}
}
MainWindow.xaml():
<Window x:Name="MW" x:Class="MyProgram.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MyProgram"
mc:Ignorable="d"
Title="MyProgram" d:DesignHeight="1080" d:DesignWidth="1920" ResizeMode="NoResize" WindowState="Maximized" WindowStyle="None" MouseLeave="HUD_MouseLeave">
<Grid x:Name="MyGrid MouseDown="HUD_MouseDown" />
<Image x:Name="Image1" Source="pic.png" Margin="880,862,0,0" Height="164" Width="162" HorizontalAlignment="Left" VerticalAlignment="Top" MouseLeftButtonDown="Control_MouseLeftButtonDown" MouseLeftButtonUp="Control_MouseLeftButtonUp" MouseMove="Control_MouseMove" />
<TextBox x:Name="Textbox1" Margin="440,560,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" MouseLeftButtonDown="Control_MouseLeftButtonDown" MouseLeftButtonUp="Control_MouseLeftButtonUp" MouseMove="Control_MouseMove" />
: , TranslateTransform . , , .
2: [] ( ). . , . ( ) 4 . 1-2 adorners, . . , , , , ResizingAdorner.
3: "" , . . , - .
4 (1/10/2018): - . , Thumb adorner , Margin 0,0. , .
5 (1/15/2018): adorner Canvas, Grid . , ArrangeOverride - ( , UIElement).