This is my new class I'm able to add elements to the panel but the drag behaviour is not working. And I want the child center to be on panel center throught the attached properties TOP=0 And LEFT=0. Is there any better way to place child elements on the center through the use of attached properties.
public class SmartCanvas : Panel
{
public static readonly DependencyProperty TopProperty;
public static readonly DependencyProperty LeftProperty;
public static readonly DependencyProperty BottomProperty;
public static readonly DependencyProperty RightProperty;
public static readonly DependencyProperty AllowDraggingProperty;
public static readonly DependencyProperty AllowDragOutOfViewProperty;
public static readonly DependencyProperty CanBeDraggedProperty;
private UIElement elementBeingDragged;
private Point origCursorLocation;
private double origHorizOffset, origVertOffset;
private bool modifyLeftOffset, modifyTopOffset;
private bool isDragInProgress;
static SmartCanvas()
{
TopProperty = DependencyProperty.RegisterAttached("Top", typeof(double), typeof(SmartCanvas), new FrameworkPropertyMetadata(0.0));
LeftProperty = DependencyProperty.RegisterAttached("Left", typeof(double), typeof(SmartCanvas), new FrameworkPropertyMetadata(0.0));
BottomProperty = DependencyProperty.RegisterAttached("Bottom", typeof(double), typeof(SmartCanvas), new FrameworkPropertyMetadata(0.0));
RightProperty = DependencyProperty.RegisterAttached("Right", typeof(double), typeof(SmartCanvas), new FrameworkPropertyMetadata(0.0));
AllowDraggingProperty = DependencyProperty.Register("AllowDragging", typeof(bool), typeof(SmartCanvas), new PropertyMetadata(true));
AllowDragOutOfViewProperty = DependencyProperty.Register("AllowDragOutOfView", typeof(bool), typeof(SmartCanvas), new UIPropertyMetadata(false));
CanBeDraggedProperty = DependencyProperty.RegisterAttached("CanBeDragged", typeof(bool), typeof(SmartCanvas), new UIPropertyMetadata(true));
}
public static void SetTop(UIElement element, double value)
{
element.SetValue(TopProperty, value);
}
public static void SetBottom(UIElement element, double value)
{
element.SetValue(BottomProperty, value);
}
public static void SetLeft(UIElement element, double value)
{
element.SetValue(LeftProperty, value);
}
public static void SetRight(UIElement element, double value)
{
element.SetValue(RightProperty, value);
}
public static double GetTop(UIElement element)
{
return (double)element.GetValue(TopProperty);
}
public static double GetBottom(UIElement element)
{
return (double)element.GetValue(BottomProperty);
}
public static double GetLeft(UIElement element)
{
return (double)element.GetValue(LeftProperty);
}
public static double GetRight(UIElement element)
{
return (double)element.GetValue(RightProperty);
}
public static bool GetCanBeDragged(UIElement uiElement)
{
if (uiElement == null) return false;
return (bool)uiElement.GetValue(CanBeDraggedProperty);
}
public static void SetCanBeDragged(UIElement uiElement, bool value)
{
if (uiElement != null)
uiElement.SetValue(CanBeDraggedProperty, value);
}
public bool AllowDragging
{
get { return (bool)base.GetValue(AllowDraggingProperty); }
set { base.SetValue(AllowDraggingProperty, value); }
}
public bool AllowDragOutOfView
{
get { return (bool)GetValue(AllowDragOutOfViewProperty); }
set { SetValue(AllowDragOutOfViewProperty, value); }
}
public void BringToFront(UIElement element)
{
this.UpdateZOrder(element, true);
}
public void SendToBack(UIElement element)
{
this.UpdateZOrder(element, false);
}
public UIElement ElementBeingDragged
{
get
{
if (!this.AllowDragging)
{
return null;
}
else
{
return this.elementBeingDragged;
}
}
protected set
{
if (this.elementBeingDragged != null)
{
this.elementBeingDragged.ReleaseMouseCapture();
}
if (!this.AllowDragging)
{
this.elementBeingDragged = null;
}
else
{
if (SmartCanvas.GetCanBeDragged(value))
{
this.elementBeingDragged = value;
this.elementBeingDragged.CaptureMouse();
}
else
{
this.elementBeingDragged = null;
}
}
}
}
public UIElement FindCanvasChild(DependencyObject depObj)
{
while (depObj != null)
{
UIElement elem = depObj as UIElement;
if (elem != null && base.Children.Contains(elem))
break;
if (depObj is Visual || depObj is Visual3D)
depObj = VisualTreeHelper.GetParent(depObj);
else
depObj = LogicalTreeHelper.GetParent(depObj);
}
return depObj as UIElement;
}
protected override Size ArrangeOverride(Size arrangeSize)
{
Point middle = new Point(arrangeSize.Width / 2, arrangeSize.Height / 2);
foreach (UIElement element in base.InternalChildren)
{
if (element == null)
{
continue;
}
double x = 0.0;
double y = 0.0;
double left = SmartCanvas.GetLeft(element);
if (!double.IsNaN(left))
{
x = left;
}
double top = SmartCanvas.GetTop(element);
if (!double.IsNaN(top))
{
y = top;
}
element.Arrange(new Rect(new Point(middle.X + x, middle.Y + y), element.DesiredSize));
}
return arrangeSize;
}
protected override Size MeasureOverride(Size availableSize)
{
Size resultSize = new Size(0, 0);
foreach (UIElement child in Children)
{
child.Measure(availableSize);
resultSize.Width = Math.Max(resultSize.Width, child.DesiredSize.Width);
resultSize.Height = Math.Max(resultSize.Height, child.DesiredSize.Height);
}
resultSize.Width = double.IsPositiveInfinity(availableSize.Width) ?
resultSize.Width : availableSize.Width;
resultSize.Height = double.IsPositiveInfinity(availableSize.Height) ?
resultSize.Height : availableSize.Height;
return resultSize;
}
protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnPreviewMouseLeftButtonDown(e);
this.isDragInProgress = false;
this.origCursorLocation = e.GetPosition(this);
this.ElementBeingDragged = this.FindCanvasChild(e.Source as DependencyObject);
if (this.ElementBeingDragged == null)
return;
double left = SmartCanvas.GetLeft(this.ElementBeingDragged);
double right = SmartCanvas.GetRight(this.ElementBeingDragged);
double top = SmartCanvas.GetTop(this.ElementBeingDragged);
double bottom = SmartCanvas.GetBottom(this.ElementBeingDragged);
this.origHorizOffset = ResolveOffset(left, right, out this.modifyLeftOffset);
this.origVertOffset = ResolveOffset(top, bottom, out this.modifyTopOffset);
e.Handled = true;
this.isDragInProgress = true;
}
protected override void OnPreviewMouseMove(MouseEventArgs e)
{
base.OnPreviewMouseMove(e);
if (this.ElementBeingDragged == null || !this.isDragInProgress)
return;
Point cursorLocation = e.GetPosition(this);
double newHorizontalOffset, newVerticalOffset;
if (this.modifyLeftOffset)
newHorizontalOffset = this.origHorizOffset + (cursorLocation.X - this.origCursorLocation.X);
else
newHorizontalOffset = this.origHorizOffset - (cursorLocation.X - this.origCursorLocation.X);
if (this.modifyTopOffset)
newVerticalOffset = this.origVertOffset + (cursorLocation.Y - this.origCursorLocation.Y);
else
newVerticalOffset = this.origVertOffset - (cursorLocation.Y - this.origCursorLocation.Y);
if (!this.AllowDragOutOfView)
{
Rect elemRect = this.CalculateDragElementRect(newHorizontalOffset, newVerticalOffset);
bool leftAlign = elemRect.Left < 0;
bool rightAlign = elemRect.Right > this.ActualWidth;
if (leftAlign)
newHorizontalOffset = modifyLeftOffset ? 0 : this.ActualWidth - elemRect.Width;
else if (rightAlign)
newHorizontalOffset = modifyLeftOffset ? this.ActualWidth - elemRect.Width : 0;
bool topAlign = elemRect.Top < 0;
bool bottomAlign = elemRect.Bottom > this.ActualHeight;
if (topAlign)
newVerticalOffset = modifyTopOffset ? 0 : this.ActualHeight - elemRect.Height;
else if (bottomAlign)
newVerticalOffset = modifyTopOffset ? this.ActualHeight - elemRect.Height : 0;
}
if (this.modifyLeftOffset)
{
SmartCanvas.SetLeft(this.ElementBeingDragged, newHorizontalOffset);
}
else
{
SmartCanvas.SetRight(this.ElementBeingDragged, newHorizontalOffset);
}
if (this.modifyTopOffset)
{
SmartCanvas.SetTop(this.ElementBeingDragged, newVerticalOffset);
}
else
{
SmartCanvas.SetBottom(this.ElementBeingDragged, newVerticalOffset);
}
}
protected override void OnPreviewMouseUp(MouseButtonEventArgs e)
{
base.OnPreviewMouseUp(e);
this.ElementBeingDragged = null;
}
private Rect CalculateDragElementRect(double newHorizOffset, double newVertOffset)
{
if (this.ElementBeingDragged == null)
{
throw new InvalidOperationException("ElementBeingDragged is null.");
}
Size elemSize = this.ElementBeingDragged.RenderSize;
double x, y;
if (this.modifyLeftOffset)
{
x = newHorizOffset;
}
else
{
x = this.ActualWidth - newHorizOffset - elemSize.Width;
}
if (this.modifyTopOffset)
{
y = newVertOffset;
}
else
{
y = this.ActualHeight - newVertOffset - elemSize.Height;
}
Point elemLoc = new Point(x, y);
return new Rect(elemLoc, elemSize);
}
private static double ResolveOffset(double side1, double side2, out bool useSide1)
{
useSide1 = true;
double result;
if (Double.IsNaN(side1))
{
if (Double.IsNaN(side2))
{
result = 0;
}
else
{
result = side2;
useSide1 = false;
}
}
else
{
result = side1;
}
return result;
}
private void UpdateZOrder(UIElement element, bool bringToFront)
{
if (element == null)
throw new ArgumentNullException("element");
if (!base.Children.Contains(element))
throw new ArgumentException("Must be a child element of the Canvas.", "element");
int elementNewZIndex = -1;
if (bringToFront)
{
foreach (UIElement elem in base.Children)
if (elem.Visibility != Visibility.Collapsed)
++elementNewZIndex;
}
else
{
elementNewZIndex = 0;
}
int offset = (elementNewZIndex == 0) ? +1 : -1;
int elementCurrentZIndex = SmartCanvas.GetZIndex(element);
foreach (UIElement childElement in base.Children)
{
if (childElement == element)
{
SmartCanvas.SetZIndex(element, elementNewZIndex);
}
else
{
int zIndex = SmartCanvas.GetZIndex(childElement);
if (bringToFront && elementCurrentZIndex < zIndex || !bringToFront && zIndex < elementCurrentZIndex)
{
SmartCanvas.SetZIndex(childElement, zIndex + offset);
}
}
}
}
}