Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8666875
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 12, 20262026-06-12T17:50:17+00:00 2026-06-12T17:50:17+00:00

I have a DragCanvas class that inherits from Canvas and that implements functionality in

  • 0

I have a DragCanvas class that inherits from Canvas and that implements functionality in order to grab, drag and resize elements. The DragCanvas class is very similar to the one provided by Josh Smith in the following article: http://www.codeproject.com/Articles/15354/Dragging-Elements-in-a-Canvas

I’d like to be able to capture keyboard events as well in order to delete elements and duplicate them. I have overriden the OnKeydown and OnPreviewKeyDown methods and placed breakpoints in there, but they are never hitting. I’m quite inexperienced in WPF and I’m not sure what am I missing. Can you help me? Thanks in advance!

Here’s the code for the drag canvas:

public class DragCanvas : Canvas
{
    #region Data

    // Stores a reference to the UIElement currently being dragged by the user.
    private UIElement elementBeingDragged;

    private UIElement elementBeingResized;

    // Keeps track of where the mouse cursor was when a drag operation began.       
    private Point origCursorLocation;

    // The offsets from the DragCanvas' edges when the drag operation began.
    private double origHorizOffset, origVertOffset;

    // Keeps track of which horizontal and vertical offset should be modified for the drag element.
    private bool modifyLeftOffset, modifyTopOffset;

    // True if a drag operation is underway, else false.
    private bool isDragInProgress;

    // True if a drag operation is underway and the mouse has moved since the process has started. This is used
    // in order to determine on left mouse up whether we should display the resize adorners or not.
    private bool hasMouseMovedInDragInProgress;

    private AdornerLayer adornerLayer;

    #endregion // Data

    #region Attached Properties

    #region CanBeDragged

    public static readonly DependencyProperty CanBeDraggedProperty;
    public static readonly DependencyProperty LineBelongsToBaseGridProperty;

    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);
    }

    #endregion // CanBeDragged

    #endregion // Attached Properties

    #region Dependency Properties

    public static readonly DependencyProperty AllowDraggingProperty;
    public static readonly DependencyProperty AllowDragOutOfViewProperty;

    #endregion // Dependency Properties

    #region Static Constructor

    static DragCanvas()
    {
        AllowDraggingProperty = DependencyProperty.Register(
            "AllowDragging",
            typeof(bool),
            typeof(DragCanvas),
            new PropertyMetadata(true));

        AllowDragOutOfViewProperty = DependencyProperty.Register(
            "AllowDragOutOfView",
            typeof(bool),
            typeof(DragCanvas),
            new UIPropertyMetadata(false));

        CanBeDraggedProperty = DependencyProperty.RegisterAttached(
            "CanBeDragged",
            typeof(bool),
            typeof(DragCanvas),
            new UIPropertyMetadata(true));

        LineBelongsToBaseGridProperty = DependencyProperty.RegisterAttached(
            "LineBelongsToBaseGrid",
            typeof(bool),
            typeof(DragCanvas),
            new UIPropertyMetadata(false));
    }

    #endregion // Static Constructor

    #region Constructor

    /// <summary>
    /// Initializes a new instance of DragCanvas.  UIElements in
    /// the DragCanvas will immediately be draggable by the user.
    /// </summary>
    public DragCanvas()
    {
    }

    #endregion // Constructor

    #region Interface

    #region AllowDragging

    /// <summary>
    /// Gets/sets whether elements in the DragCanvas should be draggable by the user.
    /// The default value is true.  This is a dependency property.
    /// </summary>
    public bool AllowDragging
    {
        get { return (bool)base.GetValue(AllowDraggingProperty); }
        set { base.SetValue(AllowDraggingProperty, value); }
    }

    #endregion // AllowDragging

    #region AllowDragOutOfView

    /// <summary>
    /// Gets/sets whether the user should be able to drag elements in the DragCanvas out of
    /// the viewable area.  The default value is false.  This is a dependency property.
    /// </summary>
    public bool AllowDragOutOfView
    {
        get { return (bool)GetValue(AllowDragOutOfViewProperty); }
        set { SetValue(AllowDragOutOfViewProperty, value); }
    }

    #endregion // AllowDragOutOfView

    #region BringToFront / SendToBack

    /// <summary>
    /// Assigns the element a z-index which will ensure that 
    /// it is in front of every other element in the Canvas.
    /// The z-index of every element whose z-index is between 
    /// the element's old and new z-index will have its z-index 
    /// decremented by one.
    /// </summary>
    /// <param name="targetElement">
    /// The element to be sent to the front of the z-order.
    /// </param>
    public void BringToFront(UIElement element)
    {
        this.UpdateZOrder(element, true);
    }

    /// <summary>
    /// Assigns the element a z-index which will ensure that 
    /// it is behind every other element in the Canvas.
    /// The z-index of every element whose z-index is between 
    /// the element's old and new z-index will have its z-index 
    /// incremented by one.
    /// </summary>
    /// <param name="targetElement">
    /// The element to be sent to the back of the z-order.
    /// </param>
    public void SendToBack(UIElement element)
    {
        this.UpdateZOrder(element, false);
    }

    #endregion // BringToFront / SendToBack

    #region ElementBeingDragged

    /// <summary>
    /// Returns the UIElement currently being dragged, or null.
    /// </summary>
    /// <remarks>
    /// Note to inheritors: This property exposes a protected 
    /// setter which should be used to modify the drag element.
    /// </remarks>
    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 (DragCanvas.GetCanBeDragged(value))
                {
                    this.elementBeingDragged = value;
                    this.elementBeingDragged.CaptureMouse();
                }
                else
                    this.elementBeingDragged = null;
            }
        }
    }

    #endregion // ElementBeingDragged

    #region FindCanvasChild

    /// <summary>
    /// Walks up the visual tree starting with the specified DependencyObject, 
    /// looking for a UIElement which is a child of the Canvas.  If a suitable 
    /// element is not found, null is returned.  If the 'depObj' object is a 
    /// UIElement in the Canvas's Children collection, it will be returned.
    /// </summary>
    /// <param name="depObj">
    /// A DependencyObject from which the search begins.
    /// </param>
    public UIElement FindCanvasChild(DependencyObject depObj)
    {
        while (depObj != null)
        {
            // If the current object is a UIElement which is a child of the
            // Canvas, exit the loop and return it.
            UIElement elem = depObj as UIElement;
            if (elem != null && base.Children.Contains(elem))
                break;

            // VisualTreeHelper works with objects of type Visual or Visual3D.
            // If the current object is not derived from Visual or Visual3D,
            // then use the LogicalTreeHelper to find the parent element.
            if (depObj is Visual || depObj is Visual3D)
                depObj = VisualTreeHelper.GetParent(depObj);
            else
                depObj = LogicalTreeHelper.GetParent(depObj);
        }
        return depObj as UIElement;
    }

    #endregion // FindCanvasChild

    #endregion // Interface

    #region Overrides

    protected override void OnKeyDown(KeyEventArgs e)
    {
        base.OnKeyDown(e);

        int b;
        b = 10;
        return;
    }

    protected override void OnPreviewKeyDown(KeyEventArgs e)
    {
        base.OnPreviewKeyDown(e);

        int b;
        b = 10;
        return;
    }

    #region OnPreviewMouseLeftButtonDown

    protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
    {
        base.OnPreviewMouseLeftButtonDown(e);

        this.isDragInProgress = false;

        // If we have a mouse button down, check whether elementBeingResized is not null.
        // If it's not, it means that we were resizing an element and we have now clicked somewhere else,
        // so remove its resizing adorner.
        if ((this.elementBeingResized != null) && (this.adornerLayer != null))
        {
            var adorners = adornerLayer.GetAdorners(elementBeingResized);
            if (adorners != null)
                adornerLayer.Remove(adorners[0]);
        }
        // Cache the mouse cursor location.
        this.origCursorLocation = e.GetPosition(this);

        // Walk up the visual tree from the element that was clicked, 
        // looking for an element that is a direct child of the Canvas.
        this.elementBeingResized = this.ElementBeingDragged = this.FindCanvasChild(e.Source as DependencyObject);
        if (this.ElementBeingDragged == null)
            return;

        if ((bool)ElementBeingDragged.GetValue(LineBelongsToBaseGridProperty))
        {
            this.ElementBeingDragged = null;
            return;
        }

        // Get the element's offsets from the four sides of the Canvas.
        double left = Canvas.GetLeft(this.ElementBeingDragged);
        double right = Canvas.GetRight(this.ElementBeingDragged);
        double top = Canvas.GetTop(this.ElementBeingDragged);
        double bottom = Canvas.GetBottom(this.ElementBeingDragged);

        // Calculate the offset deltas and determine for which sides
        // of the Canvas to adjust the offsets.
        this.origHorizOffset = ResolveOffset(left, right, out this.modifyLeftOffset);
        this.origVertOffset = ResolveOffset(top, bottom, out this.modifyTopOffset);

        // Set the Handled flag so that a control being dragged 
        // does not react to the mouse input.
        e.Handled = true;

        this.isDragInProgress = true;
    }

    #endregion // OnPreviewMouseLeftButtonDown

    protected override void OnPreviewMouseRightButtonDown(MouseButtonEventArgs e)
    {
        base.OnPreviewMouseRightButtonDown(e);
    }

    #endregion

    #region OnPreviewMouseMove

    protected override void OnPreviewMouseMove(MouseEventArgs e)
    {
        base.OnPreviewMouseMove(e);

        // If no element is being dragged, there is nothing to do.
        if (this.ElementBeingDragged == null || !this.isDragInProgress)
            return;

        hasMouseMovedInDragInProgress = true;

        // Get the position of the mouse cursor, relative to the Canvas.
        Point cursorLocation = e.GetPosition(this);

        // These values will store the new offsets of the drag element.
        double newHorizontalOffset, newVerticalOffset;

        #region Calculate Offsets

        // Determine the horizontal offset.
        if (this.modifyLeftOffset)
            newHorizontalOffset = this.origHorizOffset + (cursorLocation.X - this.origCursorLocation.X);
        else
            newHorizontalOffset = this.origHorizOffset - (cursorLocation.X - this.origCursorLocation.X);

        // Determine the vertical offset.
        if (this.modifyTopOffset)
            newVerticalOffset = this.origVertOffset + (cursorLocation.Y - this.origCursorLocation.Y);
        else
            newVerticalOffset = this.origVertOffset - (cursorLocation.Y - this.origCursorLocation.Y);

        #endregion // Calculate Offsets

        if (!this.AllowDragOutOfView)
        {
            #region Verify Drag Element Location

            // Get the bounding rect of the drag element.
            Rect elemRect = this.CalculateDragElementRect(newHorizontalOffset, newVerticalOffset);

            //
            // If the element is being dragged out of the viewable area, 
            // determine the ideal rect location, so that the element is 
            // within the edge(s) of the canvas.
            //
            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;

            #endregion // Verify Drag Element Location
        }

        #region Move Drag Element

        if (this.modifyLeftOffset)
            Canvas.SetLeft(this.ElementBeingDragged, newHorizontalOffset);
        else
            Canvas.SetRight(this.ElementBeingDragged, newHorizontalOffset);

        if (this.modifyTopOffset)
            Canvas.SetTop(this.ElementBeingDragged, newVerticalOffset);
        else
            Canvas.SetBottom(this.ElementBeingDragged, newVerticalOffset);

        #endregion // Move Drag Element
    }

    #endregion // OnPreviewMouseMove

    #region OnHostPreviewMouseUp

    protected override void OnPreviewMouseUp(MouseButtonEventArgs e)
    {
        base.OnPreviewMouseUp(e);

        if ((elementBeingResized != null) && !hasMouseMovedInDragInProgress)
        {
            // If no call to MouseMove has been issues during the drag process, it means that the user wants to resize it.
            adornerLayer = AdornerLayer.GetAdornerLayer(elementBeingResized);
            adornerLayer.Add(new ResizingAdorner(elementBeingResized));
        }
        hasMouseMovedInDragInProgress = false;

        // Reset the field whether the left or right mouse button was 
        // released, in case a context menu was opened on the drag element.
        this.ElementBeingDragged = null;
    }

    #endregion // OnHostPreviewMouseUp

    #region HostEventHandlers

    #endregion // Host Event Handlers

    #region Private Helpers

    #region CalculateDragElementRect

    /// <summary>
    /// Returns a Rect which describes the bounds of the element being dragged.
    /// </summary>
    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);
    }

    #endregion // CalculateDragElementRect

    #region ResolveOffset

    /// <summary>
    /// Determines one component of a UIElement's location 
    /// within a Canvas (either the horizontal or vertical offset).
    /// </summary>
    /// <param name="side1">
    /// The value of an offset relative to a default side of the 
    /// Canvas (i.e. top or left).
    /// </param>
    /// <param name="side2">
    /// The value of the offset relative to the other side of the 
    /// Canvas (i.e. bottom or right).
    /// </param>
    /// <param name="useSide1">
    /// Will be set to true if the returned value should be used 
    /// for the offset from the side represented by the 'side1' 
    /// parameter.  Otherwise, it will be set to false.
    /// </param>
    private static double ResolveOffset(double side1, double side2, out bool useSide1)
    {
        // If the Canvas.Left and Canvas.Right attached properties 
        // are specified for an element, the 'Left' value is honored.
        // The 'Top' value is honored if both Canvas.Top and 
        // Canvas.Bottom are set on the same element.  If one 
        // of those attached properties is not set on an element, 
        // the default value is Double.NaN.
        useSide1 = true;
        double result;
        if (Double.IsNaN(side1))
        {
            if (Double.IsNaN(side2))
            {
                // Both sides have no value, so set the
                // first side to a value of zero.
                result = 0;
            }
            else
            {
                result = side2;
                useSide1 = false;
            }
        }
        else
        {
            result = side1;
        }
        return result;
    }

    #endregion // ResolveOffset

    #region UpdateZOrder

    /// <summary>
    /// Helper method used by the BringToFront and SendToBack methods.
    /// </summary>
    /// <param name="element">
    /// The element to bring to the front or send to the back.
    /// </param>
    /// <param name="bringToFront">
    /// Pass true if calling from BringToFront, else false.
    /// </param>
    private void UpdateZOrder(UIElement element, bool bringToFront)
    {
        #region Safety Check

        if (element == null)
            throw new ArgumentNullException("element");

        if (!base.Children.Contains(element))
            throw new ArgumentException("Must be a child element of the Canvas.", "element");

        #endregion // Safety Check

        #region Calculate Z-Indici And Offset

        // Determine the Z-Index for the target UIElement.
        int elementNewZIndex = -1;
        if (bringToFront)
        {
            foreach (UIElement elem in base.Children)
                if (elem.Visibility != Visibility.Collapsed)
                    ++elementNewZIndex;
        }
        else
        {
            elementNewZIndex = 0;
        }

        // Determine if the other UIElements' Z-Index 
        // should be raised or lowered by one. 
        int offset = (elementNewZIndex == 0) ? +1 : -1;

        int elementCurrentZIndex = Canvas.GetZIndex(element);

        #endregion // Calculate Z-Indici And Offset

        #region Update Z-Indici

        // Update the Z-Index of every UIElement in the Canvas.
        foreach (UIElement childElement in base.Children)
        {
            if (childElement == element)
                Canvas.SetZIndex(element, elementNewZIndex);
            else
            {
                int zIndex = Canvas.GetZIndex(childElement);

                // Only modify the z-index of an element if it is  
                // in between the target element's old and new z-index.
                if (bringToFront && elementCurrentZIndex < zIndex ||
                    !bringToFront && zIndex < elementCurrentZIndex)
                {
                    Canvas.SetZIndex(childElement, zIndex + offset);
                }
            }
        }

        #endregion // Update Z-Indici
    }

    #endregion // UpdateZOrder

    #endregion // Private Helpers
}

Here’s the snippet in the MainWindow.xaml that creates the drag canvas:

<DragCanvas:DragCanvas x:Name="editCanvas" Margin="196,27,9,236" Background="Aquamarine" Focusable="True"/>

And here’s the constructor code in the code-behind file:

public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainWindowViewModel();

        Initialize();

        Loaded += (x, y) => Keyboard.Focus(editCanvas);
    }

    DragHelper _dragHelper;
    DropHelper _dropHelper;
    private List<Line> _gridLines = new List<Line>();

    internal void Initialize()
    {
        var callback = new ListBoxDragDropDataProvider(this.listSrc);
        _dragHelper = new DragHelper(this.listSrc, callback, null);
        _dropHelper = new DropHelper(this.editCanvas);

        MainWindowViewModel.SetMainWindowView(this);
    }

    public MainWindowViewModel MainWindowViewModel
    {
        get { return DataContext as MainWindowViewModel; }
    }
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-12T17:50:18+00:00Added an answer on June 12, 2026 at 5:50 pm

    Set Focusable="True" for your canvas, then put this snippet into your window class and set DragCanvas into focus. Hope this helps you.

    Loaded += (x,y) => Keyboard.Focus(DragCanvas);

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Have data that has this kind of structure. Will be in ascending order by
I have canvas called drawCanvas to show images and inkcanvas that is contained in
Have a web service that implements REST (sort of) , Client request is made
have written this little class, which generates a UUID every time an object of
have a nice day. I got problem when trying to create an image from
Have converted devise new session from erb to Haml but doens't work, this is
Have a look at one of my websites: moskah.com The problem is that it
Have a simple contact us XPage created. Have server side validation in place that
I have the following example code: function drawCanvas() { var canvas = document.getElementById(logoText); var
Have one Doubt In MVC Architecture we can able to pass data from Controller

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.