0

I would like to have an image button for my Wpf application. At first i was happy with this answer i've found (WPF Button with Image).

However, now i want to make a style/template out of it, so i don't need to write the same thing over and over again.

The closest i could get was this image:

Image showing the three buttons i got so far

The problem is: I've lost the background (seems like there's nothing!). I already tried to get the background back with a Rectangle, but then, the button has no animations - there's no mouse over or click different colors. Seems like by using a template i erased it all...

That's not what i wanted to. I wanted to simply set a template and have all the default colors/animations.

This is my XAML so far:

<Style x:Key="btnSave" TargetType="{x:Type Button}">
    <Setter Property="Width" Value="100"></Setter>
    <Setter Property="Height" Value="25"></Setter>
    <Setter Property="Margin" Value="5"></Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <StackPanel Orientation="Horizontal">
                    <Image Source="/Resources/save.png"></Image>

                    <ContentPresenter HorizontalAlignment="Center"
                                      VerticalAlignment="Center"/>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

What i wanted was to simply use it as:

<Button Style="{StaticResource btnSave}">Save File</Button>

And have a button with an image and default colors/animations.

Is there a simple way to do this? I don't want to mess with Triggers so far, all the links i've found about this try to teach how to make a full custom button.

2 Answers 2

1

If you want to keep the default Button template and only somewhat decorate it's content, your best bet is to facilitate the Button.ContentTemplate property. Since it's a dependency property it can be styled/bound/etc. Here's how it could look in your case:

<Style x:Key="btnSave" TargetType="{x:Type Button}">
    <Setter Property="Width" Value="100"></Setter>
    <Setter Property="Height" Value="25"></Setter>
    <Setter Property="Margin" Value="5"></Setter>
    <Setter Property="ContentTemplate">
        <Setter.Value>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <Image Source="/Resources/save.png"></Image>
                    <ContentPresenter Content="{Binding}"
                                      HorizontalAlignment="Center"
                                      VerticalAlignment="Center"/>
                </StackPanel>
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

The only differences are that you use a DataTemplate instead of ControlTemplate and you need to bind the ContentPresenter.Content property inside the template. Note that in this case we're templating the object being the value of Button.Content, hence the binding has no path specified.

Sign up to request clarification or add additional context in comments.

2 Comments

Exactly what i wanted. I wonder why i never found about ContentTemplate before, it seems so obvious. Can i ask you how you know about that? I am new to WPF and would like to research more. -- edt: i will be accepting ed's answer because you both answered equally right, but he did so in 3 minutes earlier... i'm kinda sorry i can't accept nor upvote them both.
@diego.dona I usually learn something when I am faced with a problem - be it in work or when I find a question on SO I don't know the answer to (and would like to). Then I start off with MSDN documentation, and then search SO for similar problems. If that fails, then I fall back to Google and/or simple Trial and Error method of playing around with code.
0

Easy: Use a ContentTemplate, which templatizes just the content area of the Button, not the whole thing. Button supports that because it inherits from ContentControl. Pretty much anything with a Content property in WPF will support exactly the same thing.

The DataTemplate in there has the control's Content property for its DataContext, so you bind the Content simply with {Binding}. And I took the liberty of giving the image a bit of a right margin, so it doesn't rub up against the regular button content.

<Style x:Key="btnSave" TargetType="{x:Type Button}">
    <Setter Property="Width" Value="100"></Setter>
    <Setter Property="Height" Value="25"></Setter>
    <Setter Property="Margin" Value="5"></Setter>
    <Setter Property="ContentTemplate">
        <Setter.Value>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <Image 
                        VerticalAlignment="Center" 
                        Source="/Resources/save.png"
                        Margin="0,0,8,0"
                        />

                    <ContentControl
                        Content="{Binding}"
                        VerticalAlignment="Center"
                        />
                </StackPanel>
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.