2

I've recently started using C# WPF since it has more options to decorate the controls. Now I wanted to try and make a button that has a icon with the text next to it and after a little search i found a post that seemed helpfull. And I think that im on the right way of getting what I want, But I can't figure out how I can make it so I can assign the icon for each button individually.

This is the code I'm currently using for the button:

<!-- Resource Dictionary-->
<Style TargetType="{x:Type Button}" x:Key="Test">
    <Setter Property="Background" Value="#373737" />
    <Setter Property="Foreground" Value="White" />
    <Setter Property="FontSize" Value="15" />
    <Setter Property="SnapsToDevicePixels" Value="True" />

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border CornerRadius="4" Background="{TemplateBinding Background}">
                    <Grid>
                        <Canvas x:Name="ButtonImage" Width="40" Height="40" HorizontalAlignment="Left" Margin="10,0,0,0">
                            <Canvas.Background>
                                <ImageBrush ImageSource="F:\Deze Pc\Afbeeldingen\Icons\Steel Series\Documents.ico"/>
                            </Canvas.Background>
                        </Canvas>
                        <Path x:Name="PathIcon" Width="15" Height="25" Stretch="Fill" Fill="#4C87B3" HorizontalAlignment="Left" Margin="20,0,0,0" />
                        <ContentPresenter x:Name="MyContentPresenter" Content="{TemplateBinding Content}" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="60,0,0,0" />
                    </Grid>
                </Border>

                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="#E59400" />
                        <Setter Property="Foreground" Value="White" />
                        <Setter TargetName="PathIcon" Property="Fill" Value="Black" />
                    </Trigger>

                    <Trigger Property="IsPressed" Value="True">
                        <Setter Property="Background" Value="OrangeRed" />
                        <Setter Property="Foreground" Value="White" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<!--Window Xaml -->
<Button Width="200" Height="50" VerticalAlignment="Top"  Grid.Row="2" Style="{StaticResource Test}" >
        <Button.Content>
            <StackPanel>
                <TextBlock Text="Button text here" FontSize="20" />
            </StackPanel>
        </Button.Content>
    </Button>

But now was my question, how do I make it so I can set the image on the window xaml side rather then in the resource dictionary so that I'm able to give diffrent icons to diffrent buttons without needing to make a style for each of them.

Community
  • 1
  • 1
maam27
  • 444
  • 3
  • 21

2 Answers2

1

Assuming you are not already using DataContext in the template for anything, I think the simplest approach is to just bind to that. I.e., in your template:

<Canvas x:Name="ButtonImage" Width="40" Height="40" HorizontalAlignment="Left" Margin="10,0,0,0">
    <Canvas.Background>
        <ImageBrush ImageSource="{Binding}"/>
    </Canvas.Background>
</Canvas>

Then where the style is used:

<Button Width="200" Height="50" VerticalAlignment="Top"
        Grid.Row="2" Style="{StaticResource Test}"
        DataContext="{StaticResource imageSource1}">
    <Button.Content>
        <StackPanel>
            <TextBlock Text="Button text here" FontSize="20" />
        </StackPanel>
    </Button.Content>
</Button>

Where, of course, you have declared an appropriate image source as a resource, e.g.:

<BitmapImage x:Key="imageSource1"
             UriSource="F:\Deze Pc\Afbeeldingen\Icons\Steel Series\Documents.ico"/>

Alternatives include:

  1. Use the Tag property for the same purpose. In this case it's a little more complicated: you'll need to pass the Tag property down to the Border element as e.g. <Border x:Name="root" Tag="{TemplateBinding Tag}" ...>, and then refer to it in the template as e.g. <ImageBrush ImageSource="{Binding Tag, ElementName=root}"/>
  2. Create a specific data structure to hold the property values you need. In this case, you'll still need to use DataContext and access the properties via {Binding PropertyName} syntax, so this isn't better than my main suggestion above per se. It's what you could use if you find you need to pass multiple values from the client site to the template.
Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
0

I believe you need to use DynamicResource like below,

<Image Source="{DynamicResource ResourceKey=Img}"/>

Referance

or using RelativeSource

<Image Source="{Binding Path=Tag, RelativeSource={RelativeSource TemplatedParent}}" />
Community
  • 1
  • 1
Abin
  • 2,868
  • 1
  • 23
  • 59