none
MouseOver and shape with transparent background

    Question

  • I've created the UserControl which basically consists of Canvas with path. I've added event triggers for MouseEnter and MouseLeave. It works, but only when mouse pointer is on one of filled Paths. I'd like to have it working when mouse enters Canvas rectangle. Setting Background to some color solves the problem, but I need transparent background. I should be simple..
    <Canvas>
                    <Path Fill="#ff000000" Data=" M 103.522,134.742 L 123.623,125.077 L 153.336,127.860 L 186.797,142.151 L 206.658,159.330 L 207.867,173.972 L 186.755,147.786 L 153.412,134.076 L 132.470,131.376 L 115.738,139.484 L 132.752,144.922 L 118.896,153.342 L 129.771,160.078 L 115.843,167.542 L 122.701,172.767 L 110.971,181.142 L 104.065,204.298 L 108.568,218.927 L 119.149,226.837 L 112.999,253.113 L 97.637,245.301 L 86.481,232.778 L 79.917,216.121 L 82.932,200.062 L 95.472,174.451 L 98.147,147.184 L 103.522,134.742 L 103.522,134.742 L 103.522,134.742 Z"/>
                    <Path Fill="#ff000000" Data=" M 190.253,144.842 L 207.884,162.014 L 210.765,177.845 L 193.327,205.737 L 188.526,235.545 L 178.248,254.998 L 158.986,264.008 L 157.815,263.980 L 156.538,263.900 L 154.780,263.724 L 152.865,263.605 L 150.468,263.388 L 148.072,263.171 L 145.568,262.905 L 143.173,262.690 L 140.669,262.422 L 138.482,262.043 L 136.352,261.822 L 133.306,261.035 L 132.119,260.208 L 143.739,236.264 L 161.971,233.865 L 177.295,216.806 L 178.728,196.315 L 171.629,187.163 L 184.876,187.791 L 174.129,174.409 L 187.266,174.985 L 180.383,163.436 L 196.516,167.405 L 190.253,144.842 L 190.253,144.842 L 190.253,144.842 Z"/>
    </Canvas>
    
    Wednesday, October 28, 2009 8:49 PM

Answers

  • You'll need to override the default hit testing if you want the transparent rectangle to be treated like that.

    See Hit Testing in the Visual Layer for details, in particular, the section "Overriding default hit testing".  If you implement that for your UserControl, you can get the behavior you wish.
    Reed Copsey, Jr. - http://reedcopsey.com
    • Marked as answer by Kefir0 Wednesday, October 28, 2009 9:09 PM
    Wednesday, October 28, 2009 9:02 PM
  • Sorry, I posted the previous one before I see Reed Copsey's answer:-)  Just want to share the override HitTestCore code sample:

    Markup:
    <Window x:Class="HitTesting.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:HitTesting"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <Style x:Key="MyCanvas">
                <Style.Triggers>
                    <Trigger Property="Control.IsMouseOver" Value="True">
                        <Setter Property="Control.Background" Value="Yellow" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Window.Resources>
        <local:MyCanvas Style="{StaticResource MyCanvas}">
            <TextBlock Text="Test" Width="100" Height="30"/>
        </local:MyCanvas>
    </Window>

    Code:
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;

    namespace HitTesting
    {
        public class MyCanvas : Canvas
        {
            protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
            {
                if (hitTestParameters == null)
                {
                    throw new ArgumentNullException("hitTestParameters");
                }

                Rect r = new Rect(new Point(), RenderSize);

                if (r.Contains(hitTestParameters.HitPoint))
                {
                    return new PointHitTestResult(this, hitTestParameters.HitPoint);
                }

                return null;
            }
        }
    }


    William
    • Marked as answer by Kefir0 Thursday, October 29, 2009 9:57 AM
    Wednesday, October 28, 2009 11:23 PM

All replies

  • You'll need to override the default hit testing if you want the transparent rectangle to be treated like that.

    See Hit Testing in the Visual Layer for details, in particular, the section "Overriding default hit testing".  If you implement that for your UserControl, you can get the behavior you wish.
    Reed Copsey, Jr. - http://reedcopsey.com
    • Marked as answer by Kefir0 Wednesday, October 28, 2009 9:09 PM
    Wednesday, October 28, 2009 9:02 PM
  • Thanks for your answer. I've just found the solution to set Background="#00000000" (zero opacity). However, overriding hit testing seems to be more natural solution, and can be faster maybe.
    Wednesday, October 28, 2009 9:08 PM
  • Does markup below work for you?  For some reason, we need to have Canvas.Background to be set in markup first to make the trigger working.

    <Window x:Class="ChangeCanvasBackgroundWhenMouseOver.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">
        <Window.Resources>
            <Style x:Key="MyCanvas">
                <Style.Triggers>
                    <EventTrigger RoutedEvent="Mouse.MouseEnter">
                        <EventTrigger.Actions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <ColorAnimation Storyboard.TargetProperty="(Control.Background).(SolidColorBrush.Color)" To="Transparent" Duration="0"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger.Actions>
                    </EventTrigger>
                    <EventTrigger RoutedEvent="Mouse.MouseLeave">
                        <EventTrigger.Actions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <ColorAnimation Storyboard.TargetProperty="(Control.Background).(SolidColorBrush.Color)" To="LightBlue" Duration="0"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger.Actions>
                    </EventTrigger>
                </Style.Triggers>
            </Style>
        </Window.Resources>
        <Canvas Style="{StaticResource MyCanvas}" Background="LightBlue">
            <Path Fill="#ff000000" Data=" M 103.522,134.742 L 123.623,125.077 L 153.336,127.860 L 186.797,142.151 L 206.658,159.330 L 207.867,173.972 L 186.755,147.786 L 153.412,134.076 L 132.470,131.376 L 115.738,139.484 L 132.752,144.922 L 118.896,153.342 L 129.771,160.078 L 115.843,167.542 L 122.701,172.767 L 110.971,181.142 L 104.065,204.298 L 108.568,218.927 L 119.149,226.837 L 112.999,253.113 L 97.637,245.301 L 86.481,232.778 L 79.917,216.121 L 82.932,200.062 L 95.472,174.451 L 98.147,147.184 L 103.522,134.742 L 103.522,134.742 L 103.522,134.742 Z"/>
            <Path Fill="#ff000000" Data=" M 190.253,144.842 L 207.884,162.014 L 210.765,177.845 L 193.327,205.737 L 188.526,235.545 L 178.248,254.998 L 158.986,264.008 L 157.815,263.980 L 156.538,263.900 L 154.780,263.724 L 152.865,263.605 L 150.468,263.388 L 148.072,263.171 L 145.568,262.905 L 143.173,262.690 L 140.669,262.422 L 138.482,262.043 L 136.352,261.822 L 133.306,261.035 L 132.119,260.208 L 143.739,236.264 L 161.971,233.865 L 177.295,216.806 L 178.728,196.315 L 171.629,187.163 L 184.876,187.791 L 174.129,174.409 L 187.266,174.985 L 180.383,163.436 L 196.516,167.405 L 190.253,144.842 L 190.253,144.842 L 190.253,144.842 Z"/>
        </Canvas>
    </Window>

    William
    Wednesday, October 28, 2009 9:18 PM
  • Yes, as I wrote in first post, setting canvas background to some color works. And setting it to transparent color (alpha = 0) solves the whole problem.
    Wednesday, October 28, 2009 9:23 PM
  • Sorry, I posted the previous one before I see Reed Copsey's answer:-)  Just want to share the override HitTestCore code sample:

    Markup:
    <Window x:Class="HitTesting.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:HitTesting"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <Style x:Key="MyCanvas">
                <Style.Triggers>
                    <Trigger Property="Control.IsMouseOver" Value="True">
                        <Setter Property="Control.Background" Value="Yellow" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Window.Resources>
        <local:MyCanvas Style="{StaticResource MyCanvas}">
            <TextBlock Text="Test" Width="100" Height="30"/>
        </local:MyCanvas>
    </Window>

    Code:
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;

    namespace HitTesting
    {
        public class MyCanvas : Canvas
        {
            protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
            {
                if (hitTestParameters == null)
                {
                    throw new ArgumentNullException("hitTestParameters");
                }

                Rect r = new Rect(new Point(), RenderSize);

                if (r.Contains(hitTestParameters.HitPoint))
                {
                    return new PointHitTestResult(this, hitTestParameters.HitPoint);
                }

                return null;
            }
        }
    }


    William
    • Marked as answer by Kefir0 Thursday, October 29, 2009 9:57 AM
    Wednesday, October 28, 2009 11:23 PM
  • Thank you, it works!
    Thursday, October 29, 2009 9:57 AM