1

I have a custom button Style written in XAML. It is a button with image and text. But the Image should be customizable. I need to change the Source property in designer.

My code:

 <Window.Resources>
    <ResourceDictionary>
    <Style x:Key="SSbutton" TargetType="{x:Type Button}">
            <Setter Property="Cursor" Value="Hand"/>
            <Setter Property="Background" Value="Green"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Viewbox Stretch="Uniform">
                            <Border Background="{TemplateBinding Background}" Width="{TemplateBinding Width}"
                                Height="{TemplateBinding Height}">
                                <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center">
                                    <!--I want to change this Source property-->
                                    <Image Source="img/desktop.png" Width="30" HorizontalAlignment="Left" />
                                    <TextBlock Margin="3,0,0,0" HorizontalAlignment="Right" VerticalAlignment="Center"
                                           Text="{TemplateBinding Content}" FontSize="{TemplateBinding FontSize}"/>
                                </StackPanel>
                            </Border>
                        </Viewbox>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    </ResourceDictionary>
</Window.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="25"/>
        <RowDefinition />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="90" />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Border Grid.Column="0" Grid.Row="1" Background="LightGreen">
    <StackPanel >
        <Button Style="{StaticResource SSbutton}" Width="90" Height="30" Content="Desktop" FontSize="13"
                Foreground="White"/>
    </StackPanel>
    </Border>
</Grid>

How can I do that?

Chris W.
  • 22,835
  • 3
  • 60
  • 94
Ali Tor
  • 2,772
  • 2
  • 27
  • 58

1 Answers1

1

Piggy back in to the property using an arbitrary template binding with the handy dandy Tag property;

<Style x:Key="SSbutton" TargetType="{x:Type Button}">
            <Setter Property="Cursor" Value="Hand"/>
            <Setter Property="Background" Value="Green"/>
            <!-- Set a default -->
            <Setter Property="Tag" Value="img/desktop.png"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Viewbox Stretch="Uniform">
                            <Border Background="{TemplateBinding Background}" Width="{TemplateBinding Width}"
                                Height="{TemplateBinding Height}">
                                <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center">
                                    <!--I want to change this Source property-->
                                    <Image Source="{Binding Path=Tag, RelativeSource={RelativeSource TemplatedParent}}" Width="30" HorizontalAlignment="Left" />
                                    <TextBlock Margin="3,0,0,0" HorizontalAlignment="Right" VerticalAlignment="Center"
                                           Text="{TemplateBinding Content}" FontSize="{TemplateBinding FontSize}"/>
                                </StackPanel>
                            </Border>
                        </Viewbox>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Then at the instance;

<Button Style="{StaticResource SSbutton}"
        Tag="Some/Other/Image.png"
         Width="90" Height="30" 
         Content="Desktop" 
         FontSize="13" Foreground="White"/>

Hope this helps, cheers.

Edit: Updated to reflect path considerations for templatebinding in wpf as per OP's comments.

Chris W.
  • 22,835
  • 3
  • 60
  • 94
  • Did you try it? I couldn't make it work. I made copy-paste it but it did't show the image. Am I doing something wrong? – Ali Tor Aug 25 '16 at 17:55
  • I found a related question at http://stackoverflow.com/questions/4638741/template-binding-in-control-template and changed the `{TemplateBinding Tag}` code to `{Binding Path=Tag, RelativeSource={RelativeSource TemplatedParent}}`. So it works good. If you update your question using this method or yours working, I will accept it. **Note**: But this method works only in runtime. The image shows up only at runtime not design time. – Ali Tor Aug 25 '16 at 18:11
  • 1
    Ah right sorry I didn't pay attention to the x:Type when I copy/pasted your template and just assumed it was win universal since there wasn't a WPF tag on the question. If you set the build action of the image(s) to resource and use pack uri instead of literal file paths it should work at design time also. – Chris W. Aug 26 '16 at 14:28