Rushil Paul
Rushil Paul

Reputation: 2048

Moving buttons in a Canvas

The following code is supposed to move UIElements in a canvas, when the mouse hovers over them, and the user hits Ctrl.

void keydown(Object sender, KeyEventArgs e)
        {
            if (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl)
            {
                control++;
                if (control == 1)
                {
                    drag = true;
                    elem = (UIElement)Mouse.DirectlyOver;
                }
                else
                    drag = false;
                control %= 2;
            }
        }

        void mousemove(object sender, MouseEventArgs e)
        {
            Point p = e.GetPosition(canvas);
            if (drag)
            {
                if (elem == null) return;
                //Canvas.SetLeft(myButton, p.X);  <-- this works, but then why doesn't it work when I generalize it?
                Canvas.SetLeft(elem, p.X);
                Canvas.SetTop(elem, p.Y);
            }
        }

Any Shapes component, e.g. Rectangles will move when I hover the mouse over them, and hit control..But it doesn't work with Buttons, TextBoxes, TextViews, etc. Can anyone explain?

Upvotes: 3

Views: 1478

Answers (2)

Andre Luus
Andre Luus

Reputation: 3802

My guess is that those events are swallowed by the implementation of the controls that don't work.

I'm not in front of my computer now, but isn't there a previewmousemove event? Try using that?

Update: scratch that!

Just use e.Souce. The event source is designed to be the element your likely to be interested in. You'll need to cast to UIElement, but I'm pretty sure that'll work.

Upvotes: 0

Joe White
Joe White

Reputation: 97696

The documentation for Mouse.DirectlyOver says:

Controls can be composed of multiple elements. DirectlyOver reports the specific element in the composite control the mouse pointer is over and not the control itself. For example, depending on which part of a Button the pointer is over, the DirectlyOver property could report the TextBox of the Content property or the ButtonChrome.

In other words: A Button is made up of several sub-elements, like a ButtonChrome and a TextBlock (usually not a TextBox -- I think that's a typo on the MSDN page). When you call Mouse.DirectlyOver, you're probably getting one of those elements, rather than the Button.

Since those elements are not parented to a Canvas (they're parented to something in the Button's control template, most likely a Grid), setting the Canvas.Left and Canvas.Top attached properties will have no effect.

You probably want to walk up the visual tree (using VisualTreeHelper.GetParent) until you find something you're interested in dragging. How you determine whether you're interested in any given element is up to you. You could go until you find something that's parented to your Canvas, or you could just go until you find something that's one of a given set of types (stopping when you find something that descends from Control might be a decent place to start).

Upvotes: 3

Related Questions