tags:

views:

350

answers:

2

The following XAML is simply a Polygon on a Canvas that is scaled x2000. There is a trigger that changes the Fill color for the Polygon when the mouse is over it.

Why does the box change color when you hover your mouse above and to the left of the Polygon.

<Canvas Background="Black" Height="600" Width="600">
    <Canvas.RenderTransform>
        <ScaleTransform ScaleX="2000" ScaleY="2000" />
    </Canvas.RenderTransform>
    <Polygon>
        <Polygon.Resources>
            <Style TargetType="Polygon">
                <Setter Property="Fill" Value="HotPink"/>
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter Property="Fill" Value="LimeGreen"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Polygon.Resources>
        <Polygon.Points>
            <PointCollection>
                <Point X="0.1" Y="0.1" />
                <Point X="0.2" Y="0.1" />
                <Point X="0.2" Y="0.2" />
                <Point X="0.1" Y="0.2" />
            </PointCollection>
        </Polygon.Points>
    </Polygon>
</Canvas>

If I replace the Polygon with a TextBlock, this doesn't happen. How can I avoid this from happening?

+1  A: 

This looks to me like a bug in Microsoft's hit-test code for Polygon. However, I was able to get it to stop by drawing the polygon at the origin and then translating it using Canvas.Top and Canvas.Bottom. Hope this solves your problem.

<Canvas Background="Black" Height="600" Width="600">
    <Canvas.RenderTransform>
        <ScaleTransform ScaleX="2000" ScaleY="2000" />
    </Canvas.RenderTransform>
    <Polygon Canvas.Top="0.1" Canvas.Left="0.1">
        <Polygon.Resources>
            <Style TargetType="Polygon">
                <Setter Property="Fill" Value="HotPink"/>
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter Property="Fill" Value="LimeGreen"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Polygon.Resources>
        <Polygon.Points>
            <PointCollection>
                <Point X="0.0" Y="0.0" />
                <Point X="0.1" Y="0.0" />
                <Point X="0.1" Y="0.1" />
                <Point X="0.0" Y="0.1" />
            </PointCollection>
        </Polygon.Points>
    </Polygon>
</Canvas>
PeterAllenWebb
it is not bug - it is by design for shapes, which has no layouting behaviour
Tamir
Hmmm...I'm not convinced. May play with this a bit more later.
PeterAllenWebb
I'm also of the opinion that it is a bug, because without scaling the hit-test works just fine.
Dylan
The problem with this solution (and Tamir's) is that setting top and left on the shape will not work on an ellipse or non-rectangular polygon.
Dylan
@Dylan: You can use TranslateTransform instead of Canvas.Left/Top. also it will work on any other Shape (also non-rectangular) the same way with Canvas.Top/Left@PeterAllenWebb: Shaps has no layouting, even if it works fine without translate this does not mean, that it should not hit tests original areas
Tamir
@Dylan I am fairly certain that you are mistaken. Shape inherits from FrameworkElement. Now, from MSDN: "..at the WPF framework-level there is a full layout system in place that can render any FrameworkElement derived class." But I don't see how that particular point is relevant anyway, to tell you the truth.
PeterAllenWebb
@PeterAllenWebb: The reason I'm doing this is I'm building a GIS control and am handling the map zoom by using ScaleTransform. The GIS control has shapes on it, and in deep zoom I have this issue. I've worked around it currently by reversing my logic, starting with a very large canvas and a high zoom level, and shrinking it. It's not the best solution, and would prefer to find out if this is officially a bug, or if I should be drawing shapes in a different way.Given a non-rectangular polygon, the mouse over will still fire when not over the shape top and left of it.
Dylan
Interesting. I'll spend some time with the documentation and reflector tonight to see if I can get to the bottom of it. You might also try the question on the MSDN forums. I've had Microsoft employees confirm that I had fournd WPF bugs there before...naturally...
PeterAllenWebb
Yeah. This is a known bug, and apparenly has been since late 2007, with no fix yet. :( why god why? http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8708e340-f734-4cf4-b91d-28b49fee2b72
PeterAllenWebb
A: 

It's because of Shape element (which Polygon object derrived from) layout. Your shape starts from 0,0 (not from .1,.1 as drawn) thus hit test works on left. To set shape position on Canvas you should use Canvas.Left/Top attached properties, so your code will looks like this and behaviours right

**<Polygon Canvas.Top=".1" Canvas.Left=".1">
<Polygon.Points> 
 <Point X="0" Y="0" /> 
 <Point X=".1" Y="0" />  
 <Point X=".1" Y=".1" /> 
 <Point X="0" Y=".1" />
</Polygon.Points>**
Tamir
This explanation doesn't completely make sense to me. The Shape class *does* have layout behavior. Also, with the canvas un-transformed, and the polygon coordinates set to { (100,100), (200,100), (200,200), (100,200) }. The hit test works as expected. Why should it be different under a scale transform?
PeterAllenWebb