0

I am creating a user control which is a toggle button with image. I have separate dependency properties for image when the toggle button is checked and when the toggle button is not checked.

Xaml:

   <ToggleButton IsChecked="{Binding Checked, Mode=TwoWay}">
        <Image>
            <Image.Style>
                <Style TargetType="Image">
                    <Setter Property="Source" Value="{Binding CheckedImage}"></Setter>
                        <DataTrigger Binding="{Binding IsChecked}" Value="False">
                            <Setter Property="Source" Value="{Binding UncheckedImage}"></Setter>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Image.Style>
        </Image>
    </ToggleButton>

Code behind:

public partial class ImageToggleButton : UserControl
{
    public ImageToggleButton()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    public bool Checked
    {
        get { return (bool)GetValue(IsCheckedProperty); }
        set { SetValue(IsCheckedProperty, value); }
    }

    // Using a DependencyProperty as the backing store for IsChecked.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsCheckedProperty =
        DependencyProperty.Register("Checked", typeof(bool), typeof(ImageToggleButton), null);



    public ImageSource CheckedImage
    {
        get { return (ImageSource)base.GetValue(TrueStateImageProperty); }
        set { base.SetValue(TrueStateImageProperty, value); }
    }

    // Using a DependencyProperty as the backing store for TrueStateImage.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TrueStateImageProperty =
        DependencyProperty.Register("CheckedImage", typeof(ImageSource), typeof(ImageToggleButton), null);



    public ImageSource UncheckedImage
    {
        get { return (ImageSource)base.GetValue(FalseStateImageProperty); }
        set { base.SetValue(FalseStateImageProperty, value); }
    }

    // Using a DependencyProperty as the backing store for FalseStateImage.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty FalseStateImageProperty =
        DependencyProperty.Register("UncheckedImage", typeof(ImageSource), typeof(ImageToggleButton), null);
}

MainWindow:

   <ImageToggleButton Checked="{Binding IsPlaying}" CheckedImage="{DynamicResource PauseIcon}" UncheckedImage="{DynamicResource PlayIcon}">
    </ImageToggleButton>

Is it possible to use CheckedImage as a default image so that if I am not providing UncheckedImage, then in both checked and unchecked state will show CheckedImage?

Anoop
  • 53
  • 2
  • 3
  • 9
  • You could just use a template for your button instead and use triggers to assign an image, otherwise you are recreating ToggleButton with less functionality than the original design. 9 times out of 10 you don't need UC. Like what you wrote but use an unchecked image as default and then use style to assign the checked image. Hope this makes sense. – XAMlMAX Mar 28 '19 at 22:33
  • Thanks for the idea @XAMlMAX – Anoop Apr 02 '19 at 13:09

1 Answers1

1

You could register a PropertyChangedCallback for the CheckedImage property that sets the value of the other one:

public static readonly DependencyProperty TrueStateImageProperty =
    DependencyProperty.Register("CheckedImage", typeof(ImageSource), typeof(ImageToggleButton),
        new PropertyMetadata(new PropertyChangedCallback(OnPropChanged)));

private static void OnPropChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    ImageToggleButton tb = (ImageToggleButton)d;
    if (tb.UncheckedImage == null)
        tb.UncheckedImage = (ImageSource)e.NewValue;
}

By the way, you should following the dependency property naming conventions: https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/custom-dependency-properties

mm8
  • 163,881
  • 10
  • 57
  • 88