0

I have created a template of a button, which contains an Image and a TextBlock. Since I would like to change the appearance of both, I think they need to be in the Template. But, of course, not every instance of this template should present the same text and image.

Until now, i found a promising property called "Use a custom path expression" at the "Text" / "Source"-value filed of the TextBlock / Image at:

Data Binding... > Element Property > Use a custom path expression

I would now like to set this value at the instances of the button. I already tried to manually insert a myText="Lorem Ipsum" in the XAML of the Button, but that does not seem to work.

Thank you in advance for your help!

Update: This is, how the XAML looks like:

<TextBlock [...] Text="{Binding myText, ElementName={x:Null}, FallbackValue=Lorem}"/>

How do I access this or modify this, so it can be accessed?

Update 2: There already exist bindings for the TextBlock and the Image. At the moment, the XAML of the Button looks like that:

<s:SurfaceButton Command="{Binding SearchCustomCommand}" Style="{DynamicResource BasicButton}">
    <StackPanel Orientation="Vertical" Height="60" Width="48" IsHitTestVisible="False">
        <Image Source="{StaticResource ImageSourceToolboxSearchIcon}" 
            [...]
            Stretch="Uniform" />
        <TextBlock Text="{lex:LocText ToolboxButtonSearchesCustom}" 
            FontFamily="{DynamicResource button.font}" 
            [...]
            FontSize="{DynamicResource button.size}" 
            Foreground="{DynamicResource button.color.default}"/>
    </StackPanel>
</s:SurfaceButton>

I would now like to extract the Image and Textbox to the template (which also already exists), so I could refrence the Button in a way like this (whith all the Information about sizes and colors etc in the template and only the reference to the resource in the actual instance of the button - to be able to change the image/text for echt button seperately):

<s:SurfaceButton
    Command="{Binding SearchPopularCommand}"
    Style="{DynamicResource ToolboxButtonBig}"
    ImageSource="{StaticResource ImageSourceToolboxSearchIcon}"
    TextBlockSource="{lex:LocText ToolboxButtonSearchesCustom}"/>

I already copied the whole XAML for the StackPanel and the included TextBlock and Image to the Template. Now those are shown on every Button (which is fine), but i can't change the contents of them.

I'm sorry if the description is quite poor - I'm rather new to WPF...

Update 3: After some further research, I found questions similar to mine - which obviously describe the problem better than I could:

Community
  • 1
  • 1
DIF
  • 2,470
  • 6
  • 35
  • 49

2 Answers2

1

it is not necessary to edit button's template to insert image and text, you can set Button.Content property like this:

<Button>
        <Button.Content>
            <StackPanel Orientation="Horizontal">
                <Image Source="../Images/image.png"/>
                <TextBlock Text="Lorem Ipsum"/>
            </StackPanel>
        </Button.Content>
    </Button>

and it will work well. example above can be simplified but I inserted it like this for better understanding what is going on.

EDIT: here are examples how it can be done in two different ways: overwriting template:

<Button Content="Lorem Ipsum">
        <Button.Template>
            <ControlTemplate TargetType="Button">
                <StackPanel Orientation="Horizontal">
                    <Image x:Name="ButtonImage" Source="../Images/mouseNotOverImage.png"/>
                    <ContentPresenter Margin="2"
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        RecognizesAccessKey="True" />
                </StackPanel>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="ButtonImage" Property="Source" Value="../Images/mouseOverImage.png"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Button.Template>
    </Button>

complete button template definition you can find here modifying style:

<Button>
        <Button.Style>
            <Style TargetType="Button">
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Content">
                            <Setter.Value>
                                <StackPanel Orientation="Horizontal">
                                    <Image Source="../Images/mouseOverImage.png"/>
                                    <TextBlock Text="Lorem Ipsum"/>
                                </StackPanel>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="False">
                        <Setter Property="Content">
                            <Setter.Value>
                                <StackPanel Orientation="Horizontal">
                                    <Image Source="../Images/mouseNotOverImage.png"/>
                                    <TextBlock Text="Lorem Ipsum"/>
                                </StackPanel>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
    </Button>
koshdim
  • 196
  • 4
  • Thank you for your answer! I think i need to set the image and the text in the template, because i want to change their appearance in the different states of the button (like "Normal", "MouseOver", etc.) – DIF Apr 30 '12 at 14:27
  • you can manipulate with Image's Source inside VisualStates (which are inside template), do you need an example how to do that? – koshdim May 03 '12 at 11:56
  • It would be really nice, if you could give me a small example how to do that :) – DIF May 03 '12 at 13:16
  • added examples under EDIT block. sorry, stackoverflow code insertion logic is stupid (envy) – koshdim May 04 '12 at 08:34
0

Your first option would be to define a style (or styles), e.g.

<Window.Resources>
    <Style x:Key="MyButton" TargetType="{x:Type Button}" >
        <Setter Property="Content">
            <Setter.Value>
                <Grid>
                    <Image .../>
                    <TextBlock Text="Test"/>
                </Grid>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

<Grid>
    <Button Style="{StaticResource MyButton}" />
</Grid>

Your second option would be to use Blend to make a copy of the default button style and edit that

<Window.Resources>
    <Style x:Key="MyButton" TargetType="{x:Type Button}" >
        <Setter Property="Content">
            <Setter.Value>
                <Grid>
                    <TextBlock Text="Test"/>
                </Grid>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="ButtonFocusVisual">
        <Setter Property="Control.Template">
            <Setter.Value>
                <ControlTemplate>
                    <Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
        <GradientStop Color="#F3F3F3" Offset="0"/>
        <GradientStop Color="#EBEBEB" Offset="0.5"/>
        <GradientStop Color="#DDDDDD" Offset="0.5"/>
        <GradientStop Color="#CDCDCD" Offset="1"/>
    </LinearGradientBrush>
    <SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070"/>
    <Style x:Key="MyButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
        <Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
        <Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Padding" Value="1"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Themes:ButtonChrome x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" RenderDefaulted="{TemplateBinding IsDefaulted}" SnapsToDevicePixels="true">


                        <!-- put your text and image here -->

                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>

                    </Themes:ButtonChrome>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsKeyboardFocused" Value="true">
                            <Setter Property="RenderDefaulted" TargetName="Chrome" Value="true"/>
                        </Trigger>
                        <Trigger Property="ToggleButton.IsChecked" Value="true">
                            <Setter Property="RenderPressed" TargetName="Chrome" Value="true"/>
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="#ADADAD"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>
<Grid>
    <Button Content="Button" HorizontalAlignment="Left" Margin="167,151,0,0" VerticalAlignment="Top" Width="75" Style="{DynamicResource MyButtonStyle}"/>
</Grid>

and a third option would be to create a custom control based on the default button style. You could then create dependency properties and use template bindings.

Phil
  • 42,255
  • 9
  • 100
  • 100
  • Thank you for your answer! I think the first to options you posted would provide me with a static solution, where the image is fix bound to the template, am I right? I tried to clear up my question (see the last update) to clarify that I need some sort of dynamic solution, where i could insert different contents to eacht instance of the template. – DIF May 03 '12 at 06:57
  • There's nothing to stop you creating multiple styles MyButton1, MyButton2 etc. If you need to bind to view models like then you're going to need a custom control. – Phil May 03 '12 at 16:16