4

It is not easy to explain the problem without an image and without code. For those interested, I have made a sample C#/WPF project that can be downloaded from http://rapidshare.com/files/461745095/02.WPFControlEvents.rar

It is a very small project (45KB). The problem is as follows (with my apologies for the contorted description):

A "fancy" (and rather ugly) button contains a stackpanel which in turn contains 1.) a label, 2.) a canvas, 3.) two (2) concentric ellipses, all laid out from left to right.

There is a MouseEnter and a MouseLeave event handler for the stackpanel which displays a message in the title bar indicating whether the mouse is over the stackpanel or outside of it.

The problem is: when the mouse is over the label (in turn contained in the stackpanel), the mouse is (correctly) reported as being over the stackpanel. When the mouse is moved over the canvas (which is also contained in the stackpanel), the mouse is (incorrectly?) reported as not being over the stackpanel, yet when the mouse is moved a little further to the right (over the two ellipses, which are on the canvas), the mouse is reported to be over the stackpanel again.

Why is it that when the mouse is over the canvas it is reported as not being over the stackpanel but when the mouse is over the ellipses (which are painted on the canvas) it is reported as being on the stackpanel ?.

thank you for shedding light into the problem,

John.

Hex440bx
  • 657
  • 6
  • 16
  • 1
    I don't have an answer as to why this occurs, but a practical workaround may be to use a Grid to lay out the Label and Ellipse objects, using the Margin property to position the two ellipses. This avoids the nested containers, which might be causing the behavior. – Dan Bryant May 10 '11 at 16:04
  • @Dan: I tried your suggestion. Using a Grid did not exhibit the problem even though the background of the Canvas was _not_ set to transparent (as suggested by CodeNaked below.) Thank you. – Hex440bx May 10 '11 at 16:27
  • @Anyone who may read this trying to understand/solve the same problem: changing to a Grid only _seemed_ to have solved the problem because it made the label occupy the full width of the grid. The label being hit testable and over the canvas masked the continued existence of the problem. See CodeNaked's last (or close to last) comment for a better and more complete explanation of what happened in this case. – Hex440bx May 10 '11 at 17:09
  • 1
    just to be clear, what I was suggesting was to eliminate the Canvas entirely and simply place the Ellipses in a second column in the Grid. You can use the Margin property to place them in the Grid cell which, incidentally, gives you better support for scaling of the button. It's for this reason that I very rarely use the Canvas container these days. – Dan Bryant May 10 '11 at 22:33
  • @Dan: I understand. In the test I made I still used the Canvas which was the source of the problem. Had I eliminated the canvas entirely and replaced it with a Grid, everything would have worked as you suggested. Thank you for pointing out a cleaner way. – Hex440bx May 11 '11 at 17:48

1 Answers1

2

Chances are you need to set the Background of the Canvas to Transparent. This will allow it to be "hit testable" and report mouse over events.

More info can be found here, but Canvas has a null background by default.

Community
  • 1
  • 1
CodeNaked
  • 40,753
  • 6
  • 122
  • 148
  • @CodeNaked: that was an excellent suggestion. Setting the background to transparent removed the problem. I still would like to understand what caused the original behavior, since it does not make sense to me that the mouse would be reported as being on the stackpanel when it is over the ellipses (which are not transparent) but not over when the mouse is on the unpainted canvas. – Hex440bx May 10 '11 at 16:19
  • 1
    @Hex440bx - It is explained a bit in the link above, but having a null background is a bit like setting IsHitTestVisible to false. The difference being IsHitTestVisible affects any descendants (i.e. your ellipses), while having a null background only affects that one object (i.e. your Canvas). So if the mouse is over an ellipses, any of it's ancestors will have IsMouseOver set to true. When over the Canvas, it won't "receive" any mouse events for the "null pixels", so the ancestors don't have IsMouseOver set to true. – CodeNaked May 10 '11 at 16:25
  • @CodeNaked: Now I see how that makes sense. Thank you for the additional explanation and the link - very useful. – Hex440bx May 10 '11 at 16:32
  • @CodeNaked: The explanation you gave along with Kent Boogaart's (in the link you provided) makes a lot of sense. However, now, I don't understand why the problem occurs with a stackpanel but does _not_ occur with a grid even though the Canvas background is set to null. Any ideas as to why a Grid does not exhibit the problem whereas a stackpanel does ? – Hex440bx May 10 '11 at 16:40
  • @Hex440bx - It shouldn't matter if it's a Grid or a StackPanel, as long as they both have their background set to null. If you can post some XAML then I can take a closer look. – CodeNaked May 10 '11 at 16:45
  • @CodeNaked: I only made two changes to the xaml code in the project I posted. I changed the inner stackpanel to a grid, resulting in a line like this: and, of course, I changed the corresponding closing tag from to . This changed removed the problem even though the Canvas background was still set to null. – Hex440bx May 10 '11 at 16:48
  • @Hex440bx - Isn't showing in comments. Feel free to add to your question above. – CodeNaked May 10 '11 at 16:50
  • @CoceNaked: I pressed Enter prematurely resulting in the comment getting truncated. It is now fixed. – Hex440bx May 10 '11 at 16:54
  • 1
    @Hex440bx - If you don't set Grid.Row or Grid.Column, then all the Grid children will be stacked one on top of each other. In addition, the Label has no Width so it will be stretched to fill the Grid horizontally. So technically you could remove the Canvas and see the same behavior, because the hit testing is falling on the Label, not the Canvas. – CodeNaked May 10 '11 at 16:55
  • @CodeNaked: You're absolutely right!. When I resized the Label, the problem showed up again until I set the Canvas background to transparent. Thank you very much. I really appreciate all the help you provided to make me understand what was happening. – Hex440bx May 10 '11 at 17:05