15

I've edited a template from a checkbox, then I added an image into it without defining its "Source" property.

Style :

<Style x:Key="ImageCheckbox" TargetType="{x:Type CheckBox}">
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
        <Setter Property="Background" Value="{StaticResource CheckBoxFillNormal}"/>
        <Setter Property="BorderBrush" Value="{StaticResource CheckBoxStroke}"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="FocusVisualStyle" Value="{StaticResource EmptyCheckBoxFocusVisual}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type CheckBox}">
                    <Image x:Name="image" Width="20" Height="20" Stretch="UniformToFill"/>                      
                    <ControlTemplate.Triggers>
                        <Trigger Property="HasContent" Value="true">
                            <Setter Property="FocusVisualStyle" Value="{StaticResource CheckRadioFocusVisual}"/>
                            <Setter Property="Padding" Value="4,0,0,0"/>
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>       

My question is how to pass that "Source" property (in XAML) to "ImageCheckBox" template in this code :

<CheckBox Content="" Margin="0,2,0,0" Name="btTogglePalette" Grid.Row="1" Command="Helpers:UICommands.TogglePalette" 
                              IsChecked="{Binding Path=PaletteStatus, Mode=TwoWay}" VerticalAlignment="Center" HorizontalAlignment="Center" 
                              Style="{DynamicResource ImageCheckbox}">

So that the image will show the passed parameter.

Thank you

H.B.
  • 166,899
  • 29
  • 327
  • 400
Arslan
  • 569
  • 1
  • 4
  • 14
  • 1
    This is my question :) I want to pass a Source parameter like : Source="image.ico" to ImageCheckBox; so how to expose the Image Source property in the CheckBox template ? – Arslan Sep 05 '11 at 14:57
  • See also [bind to resource keys on each item](https://stackoverflow.com/a/19399136/199364) – ToolmakerSteve Mar 17 '19 at 09:07

3 Answers3

28

You can use the Tag property

<CheckBox Tag="YourImageSource"
          Style="{DynamicResource ImageCheckbox}"/>

And then bind Source of the Image in the Template to Tag

<Image x:Name="image" Width="20" Height="20" Stretch="UniformToFill"
       Source="{Binding RelativeSource={RelativeSource TemplatedParent},
                        Path=Tag}"/>

However, I'd prefer using an Attached Property for a number of reasons.

  • The intention of using Tag isn't really clear
  • You might be using the Tag property for something else
  • You might want to use more than one ImageSource etc.

The usage of an Attached Property is exactly the same except you must put parentheses around the attached property.

<CheckBox local:ImageSourceExtension.ImageSource="YourImageSource"
          Style="{DynamicResource ImageCheckbox}"/>

In Template

<Image x:Name="image" Width="20" Height="20" Stretch="UniformToFill"
       Source="{Binding RelativeSource={RelativeSource TemplatedParent},
                        Path=(local:ImageSourceExtension.ImageSource)}"/>

And here is the attached property ImageSource

public class ImageSourceExtension
{
    public static DependencyProperty ImageSourceProperty =
        DependencyProperty.RegisterAttached("ImageSource",
                                            typeof(ImageSource),
                                            typeof(ImageSourceExtension),
                                            new PropertyMetadata(null));
    public static ImageSource GetImageSource(DependencyObject target)
    {
        return (ImageSource)target.GetValue(ImageSourceProperty);
    }
    public static void SetImageSource(DependencyObject target, ImageSource value)
    {
        target.SetValue(ImageSourceProperty, value);
    }
}
Fredrik Hedblad
  • 83,499
  • 23
  • 264
  • 266
  • 3
    Nice approach. Didn't think of using attached properties for this. +1 – Isak Savo Sep 05 '11 at 16:59
  • 1
    Nice approach like Isak said +1 – Arslan Sep 06 '11 at 07:41
  • Or if you want intellisense support, inherit new CheckBox with an extra ImageSource dependency property. `{Binding ImageSource,RelativeSource={RelativeSource AncestorType={x:Type local:MyCheckBoxWithImageSource}}}` – Cihan Yakar Jun 10 '16 at 12:41
9

There is no way to pass custom parameters to a style or template. You can only access properties on the control or bound data. That said, you may be able to abuse the checkbox's Tag property to accomplish this but I'm not 100% it will work.

The proper way to do it is to create a new custom control that derives from Checkbox and add a dependency property holding your image (of type ImageSource). That way, from your control template inside generic.xaml you can do

<!-- in generic.xaml, inside the ControlTemplate for your ImageCheckbox style -->
<Image Source="{TemplateBinding ImageSource}" />

and where you instantiate your checkbox you do

<local:ImageCheckbox ImageSource="Resources/MyImage.png" ...etc... />
Isak Savo
  • 34,957
  • 11
  • 60
  • 92
1

You need to define Source in Image of ImageCheckbox template or create your own CheckBox deriving from standard CheckBox, add dependence property of type ImageSource to custom CheckBox, define custom template with binding to Source property of newly created control.

Kirill Polishchuk
  • 54,804
  • 11
  • 122
  • 125