WPF:鼠标在控件上移动时的径向渐变
WPF: Radial Gradient as Mouse Moves Over a Control
我想在鼠标移到我的按钮上时应用径向渐变效果,如解释的那样 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:
<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>
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;
}
我的问题和目标是:
- 未正确应用径向渐变。我的意思是,径向渐变显示在我的按钮的中心,没有将鼠标放在上面,当鼠标在按钮上移动时,径向渐变始终保持在中心,径向渐变不是从我的鼠标悬停的原点生成的,就像在link 提供的三个鼠标的屏幕截图。
- 使用隐藏代码迫使我为每个按钮创建两个事件 MouseMove 和 MouseLeave。我想在没有代码的情况下做到这一点,只使用 xaml 并将所有代码放在一个文件中,就在我的样式文件中 MyButtonStyle.xaml.
第一个问题是因为:
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
设置事件处理程序。其次,资源字典可能有代码隐藏。所以你可以这样做。首先将 class 分配给您的资源字典:
<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>
我想在鼠标移到我的按钮上时应用径向渐变效果,如解释的那样 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:
<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>
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;
}
我的问题和目标是:
- 未正确应用径向渐变。我的意思是,径向渐变显示在我的按钮的中心,没有将鼠标放在上面,当鼠标在按钮上移动时,径向渐变始终保持在中心,径向渐变不是从我的鼠标悬停的原点生成的,就像在link 提供的三个鼠标的屏幕截图。
- 使用隐藏代码迫使我为每个按钮创建两个事件 MouseMove 和 MouseLeave。我想在没有代码的情况下做到这一点,只使用 xaml 并将所有代码放在一个文件中,就在我的样式文件中 MyButtonStyle.xaml.
第一个问题是因为:
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
设置事件处理程序。其次,资源字典可能有代码隐藏。所以你可以这样做。首先将 class 分配给您的资源字典:
<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>