I want to create a simple button template with an image and text inside it. But I want to keep the System button's look and feel.
How do I create it, step by step?
P.S.: I have already tried it with CustomControl
in WPF and BasedOn
property.
You can do this easily with a style and attached property:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ap="clr-namespace:MyProject.Namespace.Path.To.ButtonProperties">
...
<Style x:Key="ImageButton" TargetType="Button">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Path=(ap:ButtonProperties.Image), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"></Image>
<ContentPresenter Content="{Binding Path=Content, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"></ContentPresenter>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
...
</ResourceDictionary>
and
public class ButtonProperties
{
public static ImageSource GetImage(DependencyObject obj)
{
return (ImageSource)obj.GetValue(ImageProperty);
}
public static void SetImage(DependencyObject obj, ImageSource value)
{
obj.SetValue(ImageProperty, value);
}
public static readonly DependencyProperty ImageProperty =
DependencyProperty.RegisterAttached("Image", typeof(ImageSource), typeof(ButtonProperties), new UIPropertyMetadata((ImageSource)null));
}
Then in markup:
<Button Style="{StaticResource ImageButton}" ap:ButtonProperties.Image="{StaticResource MyImage}" Content="Test">
</Button>
This example looks pretty hideous, but you can easily change the StackPanel
to a Grid
or something similar to constrain the image proportion. Using the ContentPresenter
allows you to preserve the behaviour of a button allowing you to put any UIElement
inside, and retaining Command support etc.