|
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace TaskManagerDemo.Controls
{
[TemplatePart(Name = DragDropControl.rootElement, Type = typeof(Canvas))]
[TemplatePart(Name = DragDropControl.containerElement, Type = typeof(Panel))]
[TemplatePart(Name = DragDropControl.contentElement, Type = typeof(FrameworkElement))]
public class DragDropControl : ContentControl
{
public event EventHandler PositionChanged;
public event EventHandler Resized;
private const string rootElement = "Root";
private const string containerElement = "Container";
private const string contentElement = "Content";
#region Fields
private Point oldPoint;
private bool mouseDown = false;
private string sizingDirection = string.Empty;
private TranslateTransform transform;
protected Canvas Root;
protected Panel Container;
#endregion Fields
public DragDropControl()
{
this.DefaultStyleKey = typeof(DragDropControl);
this.SetValue(Canvas.ZIndexProperty, DragDropControl.MaxZIndex);
DragDropControl.MaxZIndex++;
transform = new TranslateTransform();
this.MouseLeftButtonDown += DragDropControl_MouseLeftButtonDown;
this.MouseLeftButtonUp += DragDropControl_MouseLeftButtonUp;
this.MouseMove += DragDropControl_MouseMove;
}
#region MaxZIndex
/// <summary>
/// Identifies the MaxZIndex dependency property.
/// </summary>
public static int MaxZIndex;
#endregion MaxZIndex
#region CanResize
/// <summary>
/// Identifies the CanResize dependency property.
/// </summary>
public static readonly DependencyProperty CanResizeProperty = DependencyProperty.Register("CanResize", typeof(bool), typeof(DragDropControl), null);
/// <summary>
/// Gets or sets the CanResize possible Value of the bool object.
/// </summary>
public bool CanResize
{
get { return (bool)GetValue(CanResizeProperty); }
set { SetValue(CanResizeProperty, value); }
}
#endregion CanResize
#region OffsetX
///
/// Identifies the OffsetX dependency property.
///
public static readonly DependencyProperty OffsetXProperty = DependencyProperty.Register("OffsetX", typeof(double), typeof(DragDropControl), null);
///
/// Gets or sets the OffsetX possible Value of the int object.
///
public double OffsetX
{
get { return (double)GetValue(OffsetXProperty); }
set
{
SetValue(OffsetXProperty, value);
this.transform.X = value;
}
}
#endregion OffsetX
#region OffsetY
///
/// Identifies the OffsetY dependency property.
///
public static readonly DependencyProperty OffsetYProperty = DependencyProperty.Register("OffsetY", typeof(double), typeof(DragDropControl), null);
///
/// Gets or sets the OffsetY possible Value of the int object.
///
public double OffsetY
{
get { return (double)GetValue(OffsetYProperty); }
set
{
SetValue(OffsetYProperty, value);
this.transform.Y = value;
}
}
#endregion OffsetY
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
Root = GetTemplateChild(rootElement) as Canvas;
Container = GetTemplateChild(containerElement) as Panel;
if (Container == null)
throw new Exception(containerElement + " is Missing in the template");
this.RenderTransform = transform;
}
protected override Size ArrangeOverride(Size finalSize)
{
Size s = base.ArrangeOverride(finalSize);
if (this.Width.ToString() == "NaN")
this.Width = this.Container.ActualWidth;
if (this.Height.ToString() == "NaN")
this.Height = this.Container.ActualHeight;
return s;
}
#region Mouse Events
private void DragDropControl_MouseMove(object sender, MouseEventArgs e)
{
Point m_newPoint = e.GetPosition(null);
if (mouseDown)
{
if (sizingDirection == string.Empty)
{
// Moving the Panel
double x, y, mainX, mainY;
MainPage parent = App.Current.RootVisual as MainPage;
if (parent != null)
{
x = e.GetPosition(null).X;
y = e.GetPosition(null).Y;
mainX = e.GetPosition(parent).X;
mainY = e.GetPosition(parent).Y;
if (((mainX > 0) && (mainX < parent.ActualWidth - 10.0)) && ((mainY > 20) && (mainY < parent.ActualHeight - this.Height - 20)))
{
this.OffsetX += m_newPoint.X - oldPoint.X;
this.OffsetY += m_newPoint.Y - oldPoint.Y;
RaisePositionChanged();
}
}
}
else
{
// Resizing the Panel
Panel p = this.Parent as Panel;
Point change = new Point(m_newPoint.X - oldPoint.X, m_newPoint.Y - oldPoint.Y);
UIElement c = this.Content as UIElement;
if (sizingDirection.IndexOf("n") > -1 && this.Height - change.Y > 2) //North
{
this.OffsetY += change.Y;
this.Height -= change.Y;
RaisePositionChanged();
RaiseResized();
}
if (sizingDirection.IndexOf("s") > -1 && this.Height + change.Y > 2) //South
{
this.Height += change.Y;
RaiseResized();
}
if (sizingDirection.IndexOf("w") > -1 && this.Width - change.X > 2) //West
{
this.OffsetX += change.X;
this.Width -= change.X;
RaisePositionChanged();
RaiseResized();
}
if (sizingDirection.IndexOf("e") > -1 && this.Width + change.X > 2) //East
{
this.Width += change.X;
}
}
oldPoint = m_newPoint;
}
else
{
// Check to see if mouse is on a resize area
if (this.CanResize)
{
sizingDirection = ResizeHitTest(m_newPoint);
SetCursor(sizingDirection);
}
}
}
private void DragDropControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (mouseDown)
{
this.Opacity = 1;
this.ReleaseMouseCapture();
mouseDown = false;
}
}
private void DragDropControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.Handled)
return;
mouseDown = true;
oldPoint = e.GetPosition(null);
this.Opacity *= 0.8;
this.CaptureMouse();
int zIndex = (int)this.GetValue(Canvas.ZIndexProperty);
if (zIndex > DragDropControl.MaxZIndex)
DragDropControl.MaxZIndex = zIndex + 1;
else if (zIndex < DragDropControl.MaxZIndex)
DragDropControl.MaxZIndex++;
this.SetValue(Canvas.ZIndexProperty, DragDropControl.MaxZIndex);
}
#endregion Mouse Events
#region Helper Methods
private string ResizeHitTest(Point pt)
{
double x0 = pt.X;
double y0 = pt.Y;
Point P = Position.GetAbsolutePosition(Container);
double x1 = P.X;
double y1 = P.Y;
double x2 = x1 + Container.ActualWidth;
double y2 = y1 + Container.ActualHeight;
// Corners
if (Math.Abs(x0 - x1) < 6 && Math.Abs(y0 - y1) < 6)
sizingDirection = "nw";
else if (Math.Abs(x0 - x1) < 6 && Math.Abs(y2 - y0) < 6)
sizingDirection = "sw";
else if (Math.Abs(x2 - x0) < 6 && Math.Abs(y2 - y0) < 6)
sizingDirection = "se";
else if (Math.Abs(x2 - x0) < 6 && Math.Abs(y0 - y1) < 6)
sizingDirection = "ne";
// Sides
else if (Math.Abs(y0 - y1) < 4)
sizingDirection = "n";
else if (Math.Abs(x2 - x0) < 4)
sizingDirection = "e";
else if (Math.Abs(y2 - y0) < 4)
sizingDirection = "s";
else if (Math.Abs(x0 - x1) < 4)
sizingDirection = "w";
else
sizingDirection = string.Empty;
return sizingDirection;
}
private void SetCursor(string resize)
{
if (resize == "n" || resize == "s")
Cursor = Cursors.SizeNS;
else if (resize == "w" || resize == "e")
Cursor = Cursors.SizeWE;
else
Cursor = Cursors.Arrow;
}
private void RaiseResized()
{
if (this.Resized != null)
Resized(this, null);
}
private void RaisePositionChanged()
{
if (this.PositionChanged != null)
PositionChanged(this, null);
}
#endregion Helper Methods
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
George Henry has worked as a software developer for more than 20 years. He is currently employed by Concur in Bellevue, Washington, USA.