tags:

views:

995

answers:

4

I have a canvas object and I am sprinkling fantastic controls all over it. I'm using a ScaleTransform object to scale the canvas so I can zoom in/out.

I have wired up the controls so that I can drag them around, and the drag and drop works well by using MouseLeftButtonDown, MouseLeftButtonUp, and MouseMove. Now, I want to work on enabling an event when I click only on the Canvas. When I read the docs for the canvas object, I see that the MouseLeftButtonDown event only fires when it's over a UIElement.

Occurs when the left mouse button is pressed (or when the tip of the stylus touches the tablet PC) while the mouse pointer is over a UIElement. (Inherited from UIElement.)

Unfortunately, I want the opposite behavior. I want to know when the mouse is clicked on the Canvas while the mouse pounter isn't over any controls. Since I'm new to Silverlight, I could be doing this the wrong way. Is there something I have overlooked? Am I going about this the wrong way? I'm looking for a little help, and perhaps a lot of direction.

+1  A: 

I'm no Silverlight gurus, but could you add a transparent UIElement to the canvas, below all other UIElements, and use it to determine if the user has clicked outside of any of the other drag/drop-able elements.

Andrew Garrison
This is what I did, and it works well.
Dan Wolchonok
+1  A: 

I think you may be interpretting the documentation wrong. According to MSDN, Canvas itself is an implementation of a UIElement:

System.Windows.UIElement
  System.Windows.FrameworkElement
    System.Windows.Controls.Panel
      System.Windows.Controls.Canvas

From my experience, and correct me if I'm wrong, MouseLeftButtonDown usually only fires for the top-most UIElement clicked. So if you implement MouseLeftButtonDown for your Canvas, it should only fire when the Canvas is clicked, and NOT when the buttons are clicked. I'd say try it out first.

Will Eddins
@guard, I have seen the opposite. When I include both methods, they both fire when I click on a UIElement that is placed on the canvas.
Dan Wolchonok
+1  A: 

You want to know when a click happens on the Canvas and isn't over other controls?

The most natural thing is to capture the Canvas's MouseLeftButtonDown. Inside of that event, take a peak to see where the click happened. Then peak at the UIElements under the click. I recommend you keep everything in absolute coordinates to keep things straight. Something like:

void Page_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    Point p = e.GetPosition(null);
    var elements =  VisualTreeHelper.FindElementsInHostCoordinates(p, App.Current.RootVisual);
    foreach (var element in elements)
    {
        //Figure out if you're over a particular UI element
    }

}
Erik Mork
I think your answer is fantastic, but I don't want to cycle through the other controls on the page when a click is fired. Thanks a lot for the helpful response.
Dan Wolchonok
Thanks Dan. good luck!
Erik Mork
A: 

In WPF, I think this would be easily solved by routed events. However, Silverlight didn't get this feature. You may want to check out VisualTreeHelper.FindElementsInHostCoordinates. This article covers it a little bit.

http://www.andybeaulieu.com/Default.aspx?tabid=67&EntryID=95

Jacob Adams