How to create a custom WPF XAML style for check box images

c#, wpf, xaml

Solution

In WPF you generally look for a control that has the functionality you need and then you make it look like you want. So if you want `CheckBox` functionality then you use `CheckBox` control and change its `Template` to be what you want. So you can create `Style` for `CheckBox` that will set your custom `Template`

<Window.Resources>
    <Style TargetType="{x:Type CheckBox}" x:Key="myCheckboxStyle">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type CheckBox}">
                    <StackPanel Orientation="Horizontal">
                        <Image x:Name="checkboxImage" Source="normal.png" Width="32"/>
                        <ContentPresenter/>
                    </StackPanel>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsChecked" Value="True">
                            <Setter TargetName="checkboxImage" Property="Source" Value="checked.png"/>
                        </Trigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsMouseOver" Value="True"/>
                                <Condition Property="IsChecked" Value="False"/>
                            </MultiTrigger.Conditions>
                            <Setter TargetName="checkboxImage" Property="Source" Value="hover.png"/>
                        </MultiTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

and then just use it on any `CheckBox`

<CheckBox Style="{StaticResource myCheckboxStyle}" Content="ABC"/>

and you'll have all `CheckBox` functionality with your custom looks

Problem

I have a C# WPF Page and on it I have placed several small images that I want to act like check boxes (I have my own custom images for hover and selected states). I am manually changing the images like so: ``` <Image x:Name="Image_Custom" Source="/Images/checkcircle_off.png" Width="16" Height="16" HorizontalAlignment="Left" Margin="30,107,0,0" VerticalAlignment="Top" MouseEnter="Image_Custom_MouseEnter" MouseLeave="Image_Custom_MouseLeave" MouseUp="Image_Custom_MouseUp" MouseLeftButtonDown="Image_Custom_MouseLeftButtonDown"/> private void Image_Custom_MouseEnter(object sender, MouseEventArgs e) { if (_selected == false) { var uriSource = new Uri("/Images/checkcircle_hover.png", UriKind.Relative); Image_Custom.Source = new BitmapImage(uriSource); } } private void Image_Custom_MouseLeave(object sender, MouseEventArgs e) { if (_selected == false) { var uriSource = new Uri("/Images/checkcircle_off.png", UriKind.Relative); Image_Custom.Source = new BitmapImage(uriSource); } } private void Image_Custom_MouseUp(object sender, MouseButtonEventArgs e) { if (_selected) { var uriSource = new Uri("/Images/checkcircle_off.png", UriKind.Relative); Image_Custom.Source = new BitmapImage(uriSource); _selected = false; } else { var uriSource = new Uri("/Images/checkcircle_on.png", UriKind.Relative); Image_Custom.Source = new BitmapImage(uriSource); _selected = true; } } private void Image_Custom_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { if (_selected) { var uriSource = new Uri("/Images/checkcircle_off.png", UriKind.Relative); Image_Custom.Source = new BitmapImage(uriSource); _selected = false; } else { var uriSource = new Uri("/Images/checkcircle_on.png", UriKind.Relative); Image_Custom.Source = new BitmapImage(uriSource); _selected = true; } } ``` This works but is very cumbersome and I will have up to 20 check boxes. How can I create a custom XAML Style that I can use for each image or something similar. EDIT: I have used the following style to handle the hover over: ``` <Page.Resources> <Style TargetType="Image" x:Key="checkBoxStyle"> <Setter Property="Source" Value="/Images/checkcircle_off.png"/> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Source" Value="/Images/checkcircle_hover.png"/> </Trigger> </Style.Triggers> </Style> </Page.Resources> <Image x:Name="Image_Custom" Style="{StaticResource checkBoxStyle}" Width="16" Height="16" HorizontalAlignment="Left" Margin="30,107,0,0" VerticalAlignment="Top" MouseEnter="Image_Custom_MouseEnter" MouseLeave="Image_Custom_MouseLeave" MouseUp="Image_Custom_MouseUp" MouseLeftButtonDown="Image_Custom_MouseLeftButtonDown"/> ``` But I dont know how to handle the clicked event. How can I do this? EDIT 2 I have did the following: ``` <Style TargetType="{x:Type CheckBox}" x:Key="myCheckBoxStyle"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type CheckBox}"> <Image x:Name="checkBoxImage" Source="/Images/checkcircle_off.png"></Image> <ControlTemplate.Triggers> <Trigger Property="IsChecked" Value="True"> <Setter TargetName="checkBoxImage" Property="Source" Value="/Images/checkcircle_on.png"/> </Trigger> <Trigger Property="IsChecked" Value="False"> <Setter TargetName="checkBoxImage" Property="Source" Value="/Images/checkcircle_off.png"/> </Trigger> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="checkBoxImage" Property="Source" Value="/Images/checkcircle_hover.png"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <CheckBox Content="My CheckBox" Style="{StaticResource myCheckBoxStyle}" Width="16" Height="16" Foreground="white" FontSize="16" HorizontalAlignment="Left" Margin="30,242,0,0" VerticalAlignment="Top" /> ``` The correct images appear when hovered, checked and unchecked. But I noticed that the Content has disappeared ("My Checkbox") and also I only want the hover state to appear when its not checked, how can I do that?

Original source