WPF - How to create image button with template
Solution 1
You won't need dependency properties because you are inheriting from Button
. You already have the IsPressed
and IsEnabled
properties. In fact, this is all you need:
<Button x:Class="TestWpfApplication.ThreeStateImageButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Image Name="Normal" Source="Resources/Normal.png"/>
<Image Name="Pressed" Source="Resources/Pressed.png" Visibility="Hidden"/>
<Image Name="Disabled" Source="Resources/Disabled.png" Visibility="Hidden"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Normal" Property="Visibility" Value="Hidden"/>
<Setter TargetName="Pressed" Property="Visibility" Value="Visible"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Normal" Property="Visibility" Value="Hidden"/>
<Setter TargetName="Disabled" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
With your UserControl code-behind file:
public partial class ThreeStateImageButton : Button
{
public ThreeStateImageButton()
{
InitializeComponent();
}
}
Solution 2
public static readonly DependencyProperty DefaultImageSourceProperty = DependencyProperty.Register("DefaultImageSource", typeof(ImageSource), typeof(PressedImageButton), new PropertyMetadata(null, new PropertyChangedCallback(DefaultImageSourceChangedCallback)));
public static readonly DependencyProperty PressedImageSourceProperty = DependencyProperty.Register("PressedImageSource", typeof(ImageSource), typeof(PressedImageButton), new PropertyMetadata(null, new PropertyChangedCallback(PressedImageSourceChangedCallback)));
public static readonly DependencyProperty ImageStretchProperty = DependencyProperty.Register("ImageStretch", typeof(Stretch), typeof(PressedImageButton), new PropertyMetadata(Stretch.None, new PropertyChangedCallback(ImageStretchChangedCallback)));
<ControlTemplate>
<Grid>
<Image Name="imgDefault" Source="{Binding Path=DefaultImageSource,ElementName=uc}" Stretch="{Binding Path=ImageStretch,ElementName=uc}"></Image>
<ContentPresenter Content="{TemplateBinding Property=ContentControl.Content}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsPressed" Value="True">
<Setter Property="Image.Source" TargetName="imgDefault" Value="{Binding Path=PressedImageSource,ElementName=uc}"></Setter>
<Setter Property="UIElement.Effect">
<Setter.Value>
<DropShadowEffect BlurRadius="10" Color="Black" Direction="0" Opacity="0.6" RenderingBias="Performance" ShadowDepth="0" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="Button.IsMouseOver" Value="True">
<Setter Property="UIElement.Effect">
<Setter.Value>
<DropShadowEffect BlurRadius="10" Color="White" Direction="0" Opacity="0.6" RenderingBias="Performance" ShadowDepth="0" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Solution 3
I have provided an alternative to this solution, its not quite as light weight but it offers much greater re-usability.
![Admin](/assets/logo_square_200-5d0d61d6853298bd2a4fe063103715b4daf2819fc21225efa21dfb93e61952ea.png)
Admin
Updated on March 11, 2020Comments
-
Admin over 4 years
I am trying to create a button which has 3 images: a Normal image, a Pressed image and a Disabled image (I will use these for creating up/down arrow buttons).
I believe the correct approach would be to derive from
Button
and use aTemplate
and set triggers to change the image. I have 3 dependency properties, one for each image.The images would be .png and have transparent backgrounds (as they are not rectangular).
I am looking for something like
CBitmapButton
in MFC. -
Anderson Imes almost 15 yearsExactly. In fact, inheriting from Button is superfluous. You can do everything with this template and a style to apply it. The rule here should be if you need to change behavior, inherit and make a control. If you need to change "Look", then use a style.
-
Admin almost 15 yearsThank you for your response. This is what I was looking for.
-
dortzur about 13 yearsTHANKS. This is the only Image Button solution that worked for me. I've even added a "Hover" trigger, Major Kudos!
-
Ash almost 13 yearswhen i am trying to add button template it shows error as the attachable property not found for button
-
surfen about 12 yearsNice solution. If anybody wondered about reusability, it's worth noticing that the image paths don't need to be hardcoded in style. If one ever needs to change something inside the style or template, for example change the button text or icon, one can use attached properties as suggested in this answer: stackoverflow.com/a/650620/724944
-
Guy almost 12 yearsHow can I pass the image src as a parameter so I can use this solution for different buttons, thanks
-
Hannish about 11 yearsThe question clearly states that they need an image button with a template. A photoshop button does not constitute a template of any kind, an besides you don't need to handle the MouseEnter and MouseLeave events to change the cursor, you have the Cursor property for that. One more thing, don't asume that the normal cursor is an arrow, it might be something else, you can set the Cursor to null to return to normal.