Pass parameter to a customized template

13,471

Solution 1

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... />

Solution 2

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);
    }
}

Solution 3

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.

Share:
13,471
Arslan
Author by

Arslan

Updated on June 05, 2022

Comments

  • Arslan
    Arslan almost 2 years

    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

  • Isak Savo
    Isak Savo over 12 years
    Nice approach. Didn't think of using attached properties for this. +1
  • Arslan
    Arslan over 12 years
    Nice approach like Isak said +1
  • Arslan
    Arslan over 12 years
    Thank you, it's the same as Isak's approach.
  • Davit Bidzhoyan
    Davit Bidzhoyan almost 8 years
    Or if you want intellisense support, inherit new CheckBox with an extra ImageSource dependency property. {Binding ImageSource,RelativeSource={RelativeSource AncestorType={x:Type local:MyCheckBoxWithImageSource}}}