0

Just tried out to write an own custom control for a button with the help of this Stackoverflow question

But the Button control is empty besides the image and the text.

Is there any possibility to use default behavior if nothing else is specified?

I do not want to re-write a whole button, if already an almost suiting exists. Just wanted to add an ImageSource and a text and some, not all, styling.

Here is what I've got, perhaps I just made some mistake.

Class definition:

public class MyImageButton : Button
{
    static MyImageButton()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(MyImageButton), new FrameworkPropertyMetadata(typeof(MyImageButton)));
    }

    public ImageSource ImageSource
    {
        get { return (ImageSource)GetValue(ImageSourceProperty); }
        set { SetValue(ImageSourceProperty, value); }
    }

    public static readonly DependencyProperty ImageSourceProperty =
        DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(MyImageButton), new UIPropertyMetadata(null));

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(MyImageButton), new UIPropertyMetadata(null));
}

From the generic.xaml

<Style TargetType="{x:Type local:MyImageButton}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:MyImageButton}">
                <StackPanel Height="Auto" Orientation="Horizontal">
                    <Image Source="{TemplateBinding ImageSource}" Width="24" Height="24" Stretch="Fill" />
                    <TextBlock Text="{TemplateBinding Text}" HorizontalAlignment="Left" Foreground="Black" FontWeight="Bold"  Margin="5,0,0,0" VerticalAlignment="Center" FontSize="12" />
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

And finally the usage in the mainwindow xaml

<ctrl:MyImageButton ImageSource="SomeImage.png" Text="BlaBlubb" Height="100" Width="120" Click="CheckClick" />
Community
  • 1
  • 1
Mare Infinitus
  • 8,024
  • 8
  • 64
  • 113
  • 1
    `Is there any possibility to use default behavior if nothing else is specified?` - I don't understand. If you inherit from `Button` you `already have` the behavior from `Button`. Did you mean appearance? these are 2 completely different (and separate) concepts in WPF. – Federico Berasategui Mar 14 '13 at 15:28
  • What I want is a button, not an image and a text. This seems to be destroyed here. I get two elements on the mainwindow, but nothing that looks close to a button – Mare Infinitus Mar 14 '13 at 15:30
  • That's because your ControlTemplate is specifying just what you are seeing - a StackPanel with an Image and a TextBlock. The ControlTemplate of a button is actually much more complex. See [this page](http://dotnet.dzone.com/news/wpf-kid-stuff-extracting) to find out how to extract the ControlTemplate of a button, or [this MSDN example](http://msdn.microsoft.com/en-us/library/ms753328%28v=vs.85%29.aspx) of a Button ControlTemplate. – Wonko the Sane Mar 14 '13 at 15:41

1 Answers1

2
But the Button control is empty besides the image and the text.

That is what you have implemented here:

<StackPanel Height="Auto" Orientation="Horizontal">
    <Image Source="{TemplateBinding ImageSource}" Width="24" Height="24" Stretch="Fill"/>
    <TextBlock Text="{TemplateBinding Text}" HorizontalAlignment="Left" Foreground="Black" FontWeight="Bold"  Margin="5,0,0,0" VerticalAlignment="Center" FontSize="12" />
</StackPanel>

What do you mean by default behavior?

An easy option would be to do this:

<Style TargetType="{x:Type local:MyImageButton}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:MyImageButton}">
                <Button>
                    <StackPanel Height="Auto" Orientation="Horizontal">
                        <Image Source="{TemplateBinding ImageSource}" Width="24" Height="24" Stretch="Fill"/>
                        <TextBlock Text="{TemplateBinding Text}" HorizontalAlignment="Left" Foreground="Black" FontWeight="Bold"  Margin="5,0,0,0" VerticalAlignment="Center" FontSize="12" />
                    </StackPanel>
                </Button>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Second option, probably best in your case:

Derive a UserControl from button, about like this:

<Button x:class="..."
        x:Name="root">
    <StackPanel Height="Auto" Orientation="Horizontal">
        <Image Source="{Binding Image, ElementName=root}" Width="24" Height="24" Stretch="Fill"/>
        <TextBlock Text="{Binding Text, ElementName=root}" HorizontalAlignment="Left" Foreground="Black" FontWeight="Bold"  Margin="5,0,0,0" VerticalAlignment="Center" FontSize="12" />
    </StackPanel>
</Button>

and define the dependency properties in the codebehind of the UserControl.

As a rule of thumb: Use UserControls, when your goal is to arrange (other) controls in a reusable way.

Marc
  • 12,706
  • 7
  • 61
  • 97