4

I have the following tree on my app:

MainWindow (Window)
> LayoutRoot (Grid)
  > (MyCustomControl)
    > Item1 (Grid)
      > Button (Button1)

MyCustomControl derives from ItemsControl and displays its items on a StackPanel.

MyCustomControl needs to know when the mouse is clicked inside itself, so i have overriden the OnPreviewMouseDown method and expected to get notified of any mouse press inside my control.

What happens: if i click inside Button1 the PreviewMouseDown event travels along the tree and OnPreviewMouseDown is executed as expected. But if i click on Item1 the the PreviewMouseDown event stops just after MainWindow and does not reach even LayoutRoot.

Here are the routed event details i got using Snoop:

Clicking Button1:

(Window)
> (Border)
  > (AdornerDecorator)
    > (ContentPresenter)
      > LayoutRoot (Grid)
        > (MyCustomControl)
          > (Border)
            > (StackPanel)
              > Item1 (Grid)
                > Button1 (Button)
                  > Chrome (ButtonChrome)

Clicking Item1:

(Window)
> (Border)

The event is never reported as handled, so it should go on tunneling as far as i know.

What am i missing here?

Zmaster
  • 1,095
  • 9
  • 23
  • If there isn't first-hand experience of this question, I think answering is difficult. So, I'd recommend you put some code. – Jin-Wook Chung Jun 18 '11 at 14:03

1 Answers1

6

You would need to ensure that your custom control is hit-testable. If you have a ControlTemplate like:

<ControlTemplate>
    <ItemsPresenter />
</ControlTemplate>

Then your custom control won't be hit-testable, by itself. Even if you have a ControlTemplate like:

<ControlTemplate>
    <Border Background="{TemplateBinding Background}" ...>
        <ItemsPresenter />
    </Border>
</ControlTemplate>

Then if Background is null, then your control won't be hit-testable, by itself. If you simply set the Background property to Transparent, then it will be hit-testable.

The rule of thumb is if your control or one of it's descendents does not render something at a given location (i.e. pixel), even if it's Transparent, then the mouse won't register events for it.

CodeNaked
  • 40,753
  • 6
  • 122
  • 148
  • Great! That was the problem. After going deeper I discovered that for an area to be hit-testable the _IsHitTestVisible property must be true AND the color must be != null_. – Zmaster Jun 19 '11 at 10:14
  • This answer solved my issue as well (ItemsControl within a Canvas, within a DockPanel) – Fortmann May 05 '17 at 11:59
  • To add to this: If you have a custom OnRender then simply setting Background will not work. Your rendering code must draw to all the pixels that you want to be hit-testable. i.e. fill the background with `drawingContext.DrawRectangle(brush, pen, new Rect(0,0,ActualWidth,ActualHeight))` or similar. – Jason Williams Feb 10 '18 at 13:16