WPF:鼠标移动到控件上时的径向渐变

时间:2017-11-11 20:25:40

标签: c# wpf xaml visual-studio-2008 gradient

我希望将鼠标移动到我的按钮上时应用径向渐变效果,如here所述。所以我有一个单独的资源文件,我在其中定义了我的按钮样式。

MyButtonStyle.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:MyTestButtons">
    <Style TargetType="Button" x:Key="MyButtonStyle">
        <!--<Setter Property="Background" Value="Transparent" />-->
        <Setter Property="TextBlock.TextAlignment" Value="Center" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">                   
                    <Border  Name="Border" CornerRadius="0"  
                             BorderBrush="#000" BorderThickness="1,1,1,1" 
                             Background="{TemplateBinding Background}">
                        <ContentPresenter x:Name="contentPresenter" 
                                          ContentTemplate="{TemplateBinding ContentTemplate}" 
                                          Content="{TemplateBinding Content}" 
                                          HorizontalAlignment="{TemplateBinding HorizontalAlignment}" 
                                          Margin="{TemplateBinding Padding}" 
                                          VerticalAlignment="{TemplateBinding VerticalAlignment}" />
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

我按下面的按钮申请。

窗口

<Window x:Class="MyTestButtons"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary  Source="/MyButtonStyle.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

   <Button Name="btnYes" Content="Yes"  
        Margin="3,5" MinWidth="70" Height="35" 
        Click="Button_Click" Foreground="Black" FontSize="14" 
        Style="{StaticResource MyButtonStyle}"  
         VerticalAlignment="Center" 
        HorizontalAlignment="Stretch"  
        VerticalContentAlignment="Center" 
        HorizontalContentAlignment="Center" 
        MouseMove="btnYes_MouseMove" 
        MouseLeave="btnYes_MouseLeave">
    <Button.Background>
        <RadialGradientBrush x:Name="gradRadial" RadiusX="0.25">
            <GradientStop Color="AliceBlue" Offset="0.0"/>
            <GradientStop Color="LightSteelBlue" Offset="1.0"/>
        </RadialGradientBrush>
    </Button.Background>
   </Button>
</Window>

窗口代码隐藏

    private void btnYes_MouseMove(object sender, MouseEventArgs e)
    {
        Point pt = Mouse.GetPosition(btnYes);
        gradRadial.GradientOrigin = new Point(pt.X / btnYes.Width, pt.Y / btnYes.Height);
        gradRadial.Center = gradRadial.GradientOrigin;
    }

    private void btnYes_MouseLeave(object sender, MouseEventArgs e)
    {
        gradRadial.GradientOrigin = new Point(0.5, 0.5);   // Default
        gradRadial.Center = gradRadial.GradientOrigin;
    }

我的问题和目标是:

  1. 未正确应用径向渐变。我的意思是,径向渐变显示在我的按钮的中心而没有将鼠标放在上面,当鼠标在按钮上移动时,径向渐变始终保持在中心,径向渐变不是从鼠标所在的原点生成的,就像在所提供的link中显示的三只鼠标的屏幕截图。
  2. 使用后面的代码强制我为每个按钮创建两个事件,MouseMove和MouseLeave。我想在没有代码的情况下完成它,只使用xaml并将所有代码放在一个文件中,就在我的样式文件MyButtonStyle.xaml中。

1 个答案:

答案 0 :(得分:3)

Fisrt问题因此而发生:

gradRadial.GradientOrigin = new Point(pt.X / btnYes.Width, pt.Y / btnYes.Height);

您使用btnYes.Width但是没有为您的按钮设置此属性,并且默认情况下它没有定义值(double.NaN),因此最终得到Point,其中一个组件未定义(无论那意味着什么)。而是使用

gradRadial.GradientOrigin = new Point(pt.X / btnYes.ActualWidth, pt.Y / btnYes.ActualHeight);

至于第二个问题。首先,样式可以通过EventSetter设置事件处理程序。其次,资源词典可能具有代码隐藏功能。所以你可以做到这一点。首先将类分配给资源字典:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                x:Class="WpfApplication1.Resources">
</ResourceDictionary>

然后定义代码隐藏:

// this is in namespace WpfApplication1
partial class Resources : ResourceDictionary {
    public Resources() {
        InitializeComponent();
    }

    private void OnMyButtonMouseLeave(object sender, MouseEventArgs e) {
        var btn = (Button) sender;
        var gradient = btn.Background as RadialGradientBrush;
        if (gradient == null)
            return;
        gradient.GradientOrigin = new Point(0.5, 0.5); // Default
        gradient.Center = gradient.GradientOrigin;
    }

    private void OnMyButtonMouseMove(object sender, MouseEventArgs e) {
        var btn = (Button) sender;
        var gradient = btn.Background as RadialGradientBrush;
        if (gradient == null)
            return;
        Point pt = Mouse.GetPosition(btn);
        gradient.GradientOrigin = new Point(pt.X / btn.ActualWidth, pt.Y / btn.ActualHeight);
        gradient.Center = gradient.GradientOrigin;
    }
}

然后以样式分配处理程序:

<Style TargetType="Button"
       x:Key="MyButtonStyle">
    <!-- skipped -->
    <EventSetter Event="MouseLeave" Handler="OnMyButtonMouseLeave"/>
    <EventSetter Event="MouseMove" Handler="OnMyButtonMouseMove"/>
</Style>