如何制作一个图像按钮,当鼠标悬停在按钮 WPF 上时改变图像?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17657048/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to make a image button that change the image when mouse over button WPF?
提问by Assaf Zigdon
I am trying to make an image button that changes the image when the mouse is over the button, i tried few things
我正在尝试制作一个图像按钮,当鼠标悬停在按钮上方时会改变图像,我尝试了一些方法
this is the last thing I tried but it doesn't work:
这是我尝试的最后一件事,但它不起作用:
<Button Name="fileNameLink" Margin="15,6,30,1" VerticalAlignment="Top" Click="btnMinimize_Click" MaxWidth="250" Background="Transparent" Cursor="Hand" Visibility="Visible" Height="16">
<Button.Template>
<ControlTemplate TargetType="Button">
<StackPanel>
<Image Name="image1" Source="{StaticResource Minimize1}" Stretch="None" Visibility="Collapsed"/>
<Image Name="image2" Source="{StaticResource Minimize2}" Stretch="None" Visibility="Visible"/>
<StackPanel.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="image1" Property="Visibility" Value="Visible"/>
<Setter TargetName="image2" Property="Visibility" Value="Collapsed"/>
</Trigger>
</StackPanel.Triggers>
</StackPanel>
</ControlTemplate>
</Button.Template>
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
i am tring to use the XAML only, without the cs file Thanks
我想只使用 XAML,不使用 cs 文件 谢谢
回答by Viv
Your Trigger's are applied to the StackPanel. It needs to be set on the ControlTemplate
您的触发器应用于StackPanel. 它需要设置在ControlTemplate
Try:
尝试:
<Button Name="fileNameLink"
Height="16"
MaxWidth="250"
Margin="15,6,30,1"
VerticalAlignment="Top"
Click="btnMinimize_Click"
Background="Transparent"
Cursor="Hand"
Visibility="Visible">
<Button.Template>
<ControlTemplate TargetType="Button">
<StackPanel>
<Image Name="image1"
Source="{StaticResource Minimize1}"
Stretch="None"
Visibility="Collapsed" />
<Image Name="image2"
Source="{StaticResource Minimize2}"
Stretch="None"
Visibility="Visible" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver"
Value="true">
<Setter TargetName="image1"
Property="Visibility"
Value="Visible" />
<Setter TargetName="image2"
Property="Visibility"
Value="Collapsed" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
In such cases. You can just use the Triggerto set the Image's source thereby not having to play with switching Visibilityon multiple UI element's.
在这种情况下。您可以只使用Trigger来设置Image的源,从而不必切换Visibility多个 UI 元素。
something like:
就像是:
<Button Name="fileNameLink"
Height="16"
MaxWidth="250"
Margin="15,6,30,1"
VerticalAlignment="Top"
Click="btnMinimize_Click"
Background="Transparent"
Cursor="Hand"
Visibility="Visible">
<Button.Template>
<ControlTemplate TargetType="Button">
<Image Name="image"
Source="{StaticResource Minimize1}"
Stretch="None" />
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver"
Value="true">
<Setter TargetName="image"
Property="Source"
Value="{StaticResource Minimize2}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
回答by Stacked
You will need a helper class to attach the image source property per button state and a style for your button. Put the helper class in a Helpersfolder in your WPF project.
您将需要一个辅助类来附加每个按钮状态的图像源属性和按钮的样式。将帮助程序类放在HelpersWPF 项目的文件夹中。
Helper class
帮手类
public static class ImageLoader
{
public static ImageSource GetDefaultImage(DependencyObject obj)
{
return (ImageSource)obj.GetValue(DefaultImageProperty);
}
public static void SetDefaultImage(DependencyObject obj, ImageSource value)
{
obj.SetValue(DefaultImageProperty, value);
}
public static readonly DependencyProperty DefaultImageProperty =
DependencyProperty.RegisterAttached(
"DefaultImage",
typeof(ImageSource),
typeof(ImageLoader),
new UIPropertyMetadata(null));
public static ImageSource GetHoverImage(DependencyObject obj)
{
return (ImageSource)obj.GetValue(HoverImageProperty);
}
public static void SetHoverImage(DependencyObject obj, ImageSource value)
{
obj.SetValue(HoverImageProperty, value);
}
public static readonly DependencyProperty HoverImageProperty =
DependencyProperty.RegisterAttached(
"HoverImage",
typeof(ImageSource),
typeof(ImageLoader),
new UIPropertyMetadata(null));
public static ImageSource GetDisabledImage(DependencyObject obj)
{
return (ImageSource)obj.GetValue(DisabledImageProperty);
}
public static void SetDisabledImage(DependencyObject obj, ImageSource value)
{
obj.SetValue(DisabledImageProperty, value);
}
public static readonly DependencyProperty DisabledImageProperty =
DependencyProperty.RegisterAttached(
"DisabledImage",
typeof(ImageSource),
typeof(ImageLoader),
new UIPropertyMetadata(null));
}
Button Style
按钮样式
<ResourceDictionary ...
xmlns:helper="clr-namespace:MySolution.MyWPFProject.Helpers"
...
>
<Style TargetType="{x:Type Button}" x:Key="MyButtonStyle">
...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<ContentPresenter Name="content"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
/>
<Border>
<!-- Default image -->
<Image Name="image" Source="{TemplateBinding helper:ImageLoader.DefaultImage}" />
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand" />
<!-- Hover image -->
<Setter TargetName="image" Property="Source" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Button}, Path=(helper:ImageLoader.HoverImage)}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<!-- Disabled image -->
<Setter TargetName="image" Property="Source" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Button}, Path=(helper:ImageLoader.DisabledImage)}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Usage
用法
<UserControl ...
xmlns:helper="clr-namespace:MySolution.MyWPFProject.Helpers"
...
>
<UserControl.Resources >
<ResourceDictionary Source="Path-to-my-button-style.xaml" />
</UserControl.Resources>
...
<Button helper:ImageLoader.DefaultImage="Resources/Images/MyDefaultImage.png"
helper:ImageLoader.HoverImage="Resources/Images/MyHoverImage.png"
helper:ImageLoader.DisabledImage="Resources/Images/MyDisabledImage.png"
Style="{DynamicResource MyButtonStyle}" />
...
回答by kmatyaszek
You can achieve this by Imagestyle:
您可以通过Image样式实现此目的:
<Button Name="fileNameLink" VerticalAlignment="Top" Click="btnMinimize_Click" MaxWidth="250" Height="100">
<Button.Content>
<StackPanel>
<Image Name="image1" Source="{StaticResource Minimize1}" Stretch="None" >
<Image.Style>
<Style TargetType="Image">
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" Value="True">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<Image Name="image2" Source="{StaticResource Minimize2}" Stretch="None" >
<Image.Style>
<Style TargetType="Image">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</StackPanel>
</Button.Content>
</Button>
回答by dowhilefor
Here is another approach to handle it using a specialized style. It should be pointed out, that this could be further improved with using attached properties for customizing the image files properly.
这是使用专门样式处理它的另一种方法。应该指出的是,这可以通过使用附加属性来正确自定义图像文件来进一步改进。
<Style x:Key="ButtonStyle" TargetType="Button">
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid>
<Rectangle Fill="Transparent"/>
<Image x:Name="img" Width="64" Height="64" Source="a.jpg"/>
</Grid>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="img" Property="Source" Value="b.jpg"/>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
The Rectangle is important for the hit testing, otherwise the IsMouseOver won't trigger. And the Stretch on the ContentAlignment is necessary otherwise the ContentPresenter of the button would not span the whole button, therefore IsMouseOver wouldn't trigger again.
矩形对于命中测试很重要,否则 IsMouseOver 将不会触发。并且 ContentAlignment 上的 Stretch 是必要的,否则按钮的 ContentPresenter 不会跨越整个按钮,因此 IsMouseOver 不会再次触发。

