I have this XAML code:
<Window x:Class="TTT_01.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" MouseLeftButtonDown="Window_MouseLeftButtonDown">
<Canvas>
<Rectangle Canvas.Left="146" Canvas.Top="110" Height="100" Name="rectangle1" Stroke="Black" Width="200" />
</Canvas>
</Window>
and this is the C# code behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (rectangle1.IsMouseOver)
{
MessageBox.Show("Click!");
}
}
}
What I see is a white rectangle. When I click into the rectangle I expect the message box to pop up. This doesn't happen though, unless I initialize the Fill
property of the rectangle either in XAML or in the MainWindow constructor. Without Fill
being initialized rectangle1.IsMouseOver
remains false
even though I click into the rectangle.
What does Fill
have to do with IsMouseOver
?
The fill is part of what specifies the hit test area of your controls. In WPF controls generally do a pixel-perfect hit test, not a rectangular one. For example, if you put an <Ellipse/>
in you XAML, clicking outside of the circumference, but inside the bounding rectangle won't generate a MouseDown event in the Ellipse (this one is kind of obvious though). In the same way not specifying a Fill for a Shape means that the inside of the shape simply doesn't exist - it hit tests negatively and lets clicks fall through. In other words, shapes without a Fill only constitute of their outline for purposes of hit testing.
If you want to have a border-only transparent rectangle (or any other Shape
) that still hit tests on the inside, then specify Fill="Transparent"
.
This is true not only for shapes, but also for containers like Grid
and Border
- if you don't specify a Background
, then their empty area doesn't register in hit testing.