WPF中的按钮以奇怪的方式使用isMouseOver

时间:2015-12-30 07:41:47

标签: c# .net wpf visual-studio

我在WPF和按钮样式中遇到了一个有趣的问题。问题是它包含一个路径,并且isMouseOver似乎只在鼠标指针位于路径上但不在按钮上时触发。那就是我必须将鼠标指针移动到按钮内的白色图形上才能使按钮着色。好像按钮不存在而且只有路径。

这是按钮的代码:

<Button Grid.Column="5" x:Name="btnClose" Width="30" Height="30" BorderBrush="White"
        BorderThickness="0" Style="{StaticResource MenuButtonStyle}"
        Command="{Binding ExitCommand}">
    <Path Data="M0,0 L16,16 M16,0 L0,16" Stroke="White" StrokeThickness="3" 
          Margin="0,1,0,0" StrokeEndLineCap="Round" StrokeStartLineCap="Round" />
</Button>

这就是风格:

<Style x:Key="MenuButtonStyle" TargetType="Button">
    <Setter Property="Width" Value="80" />
    <Setter Property="Height" Value="80" />
    <Setter Property="Margin" Value="0,0,0,0" />
    <Setter Property="FontSize" Value="13.5"/>
    <Setter Property="Foreground" Value="Red"/>
    <Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
    <Setter Property="OverridesDefaultStyle" Value="True"/>
    <Setter Property="ToolTipService.ShowOnDisabled" Value="True"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Border CornerRadius="2.5" 
                        x:Name="ButtonBorder" 
                        BorderThickness="1.2" 
                        RenderTransformOrigin="0.5,0.5">
                    <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0">

                        <Border x:Name="ButtonShine" Grid.Row="0" VerticalAlignment="Stretch"
                                HorizontalAlignment="Stretch" >
                            <!--<Border.Effect>
                                    <DropShadowEffect ShadowDepth="1" BlurRadius="1" RenderingBias="Quality" Direction="270" />
                                </Border.Effect>-->
                        </Border>
                        <ContentPresenter Grid.Row="0" VerticalAlignment="Center"
                                          HorizontalAlignment="Center" />
                        <Border x:Name="shadowMouseOver" Grid.Row="0" Visibility="Hidden"
                                VerticalAlignment="Stretch" HorizontalAlignment="Stretch" 
                                Background="#7F171717">
                        </Border>
                        <Border x:Name="shadowDisabled" Grid.Row="0" Visibility="Hidden"
                                VerticalAlignment="Stretch" HorizontalAlignment="Stretch" 
                                Background="#AFFFFFFF">
                        </Border>
                    </Grid>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="Button.IsEnabled" Value="false">
                        <Setter Property="Button.Foreground" Value="#FFDEDEDE" />
                        <Setter Property="Visibility" TargetName="shadowDisabled" Value="Visible"/>
                    </Trigger>
                    <Trigger Property="Button.IsMouseOver" Value="true">
                        <Setter Property="Visibility" TargetName="shadowMouseOver" Value="Visible"/>
                    </Trigger>
                    <Trigger Property="Button.IsPressed" Value="true">
                        <Setter Property="Button.RenderTransformOrigin" Value="0.5,0.5"/>
                        <Setter Property="Button.RenderTransform">
                            <Setter.Value>
                                <ScaleTransform ScaleX="0.95" ScaleY="0.95"/>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Visibility" TargetName="shadowMouseOver" Value="Visible"/>
                        <Setter Property="Background" TargetName="ButtonShine" >
                            <Setter.Value>
                                <LinearGradientBrush  EndPoint="0.5,1" StartPoint="0.5,0">
                                     <GradientStop Color="#FFBFBFBF" Offset="1"/>
                                     <GradientStop Color="#FF383838"/>
                                </LinearGradientBrush>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="BorderBrush" TargetName="ButtonShine" >
                            <Setter.Value>
                                <LinearGradientBrush  EndPoint="0.5,1" StartPoint="0.5,0">
                                    <GradientStop Color="#FFBFBFBF" Offset="1"/>
                                    <GradientStop Color="#FF383838"/>
                                </LinearGradientBrush>
                            </Setter.Value>
                         </Setter>
                     </Trigger>
                 </ControlTemplate.Triggers>
             </ControlTemplate>
         </Setter.Value>
     </Setter>
 </Style>

有什么想法吗? WPF中的错误?什么事做得不好?

1 个答案:

答案 0 :(得分:2)

这绝对不是一个错误,但是由于你在模板中没有为默认状态提供控件的背景;因此,命中测试在路径之外的区域中失败。如果您注意到shadowMouseOvershadowDisabled,则只有两个提供任何背景的边框才会显示,除非触发了相应的事件。因此,它们在测试中是不可见的。另一方面,您的路径是可见的,因此它可以触发事件。

有关详细信息,请参阅MSDN上的Hit Testing in the Visual Layerhttps://msdn.microsoft.com/library/ms752097(v=vs.100).aspx

以防链接在将来的某个时间失败,这里的部分内容几乎总结了我在这里要说的内容:

  

VisualTreeHelper类中的HitTest方法的目的是   确定几何或点坐标值是否在   呈现给定对象的内容,例如控件或图形   元件。例如,您可以使用命中测试来确定是否   鼠标在对象的边界矩形内单击   圆的几何形状。您也可以选择覆盖默认值   执行命中测试以执行您自己的自定义命中测试   计算。下图显示了这种关系   在非矩形对象的区域和其边界矩形之间。

enter image description here

如果您希望保持透明背景外观,可以选择几个选项。将该背景设置为Transparent,因为透明对象可见到命中测试,或将其设置为某种颜色,同时将其不透明度降低到0.该背景的最佳位置可能是{{1} 1}}(大多数外边框),但这是你的决定。