具有奇怪行为的WPF按钮的自定义悬停效果

时间:2015-07-14 15:35:10

标签: wpf hover mouseover

我有一个包含图片的简单按钮:

    <Button x:Name="helpBtn" Width="25" Style="{StaticResource HoverButton}" Template="{StaticResource hoverButtonTemplate}" Click="onHelpButtonClicked" ToolTip="{x:Static resx:language.HelpButton}" Height="25" BorderThickness="0" Canvas.Top="2" Canvas.Right="52" Canvas.Left="-77">
       <Image x:Name="helpImg" Source="Resources/2_help.png" Width="6" Height="10" Stretch="Uniform"/>
    </Button>

然后我有了这个ContentTemplate:

    <ControlTemplate x:Key="hoverButtonTemplate" TargetType="{x:Type Button}">
        <Grid>
            <ContentPresenter Content="{TemplateBinding Button.Content}" />
            <Rectangle x:Name="hoverRect2" Fill="DarkGreen" Visibility="Hidden" Opacity="0.2" Width="{TemplateBinding Button.Width}" Height="{TemplateBinding Button.Height}"></Rectangle>
            <Rectangle x:Name="hoverRect" Fill="Black" Visibility="Hidden" Opacity="1" Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content.Width}" Height="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content.Height}" Margin="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content.Margin}">
                <Rectangle.OpacityMask>
                    <ImageBrush Stretch="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content.Stretch}" ImageSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content.Source}"/>
                </Rectangle.OpacityMask>
            </Rectangle>
        </Grid>
        <ControlTemplate.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter TargetName="hoverRect" Property="Visibility" Value="Visible" />
                <Setter TargetName="hoverRect2" Property="Visibility" Value="Visible" />
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

问题是,鼠标指针始终需要在图像上移动(显示带有透明背景的小问号)。因此,在按钮的悬停效果变为可见之前,鼠标指针需要准确地悬停问号。如果悬停效果变为活动状态且鼠标离开问号但仍在按钮区域内,则一切正常。这种奇怪行为的原因是什么?

1 个答案:

答案 0 :(得分:2)

WPF不使用矩形的尺寸来检测鼠标是否在控件的内部(悬停)。控件必须以某种方式“捕获”鼠标移动事件。在您的情况下,只需在ContentPresenter下面添加一个透明层。一旦检测到悬停,可见层“捕获”了鼠标事件。

    <ControlTemplate x:Key="hoverButtonTemplate" TargetType="{x:Type Button}">
        <Grid>
            <Rectangle Fill="Transparent"/>
            <ContentPresenter Content="{TemplateBinding Button.Content}" />
            <Rectangle x:Name="hoverRect2" Fill="DarkGreen" Visibility="Hidden" Opacity="0.2" Width="{TemplateBinding Button.Width}" Height="{TemplateBinding Button.Height}"></Rectangle>
            <Rectangle x:Name="hoverRect" Fill="Black" Visibility="Hidden" Opacity="1" Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content.Width}" Height="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content.Height}" Margin="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content.Margin}">
                <Rectangle.OpacityMask>
                    <ImageBrush Stretch="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content.Stretch}" ImageSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content.Source}"/>
                </Rectangle.OpacityMask>
            </Rectangle>
        </Grid>
        <ControlTemplate.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter TargetName="hoverRect" Property="Visibility" Value="Visible" />
                <Setter TargetName="hoverRect2" Property="Visibility" Value="Visible" />
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>