user2381422
user2381422

Reputation: 5805

Code design for a toggle button in WPF

I have toggle button in WPF and when the user clicks it changes its icon. What is the best design for this? When the button is clicked the event handler is called. What then? Should I use dependency properties?

Thanks

Upvotes: 0

Views: 1334

Answers (3)

nmclean
nmclean

Reputation: 7724

It can be done through style triggers:

<Setter Property="Content">
    <Setter.Value>
        <Image Source="UncheckedImage.png" />
    </Setter.Value>
</Setter>
<Style.Triggers>
    <Trigger Property="IsChecked" Value="True">
        <Setter Property="Content">
            <Setter.Value>
                <Image Source="CheckedImage.png" />
            </Setter.Value>
        </Setter>
    </Trigger>
</Style.Triggers>

Note that if you ever set Content directly (i.e. ToggleButton.Content in XAML or property assignment in C#/VB), this would override the style setter and trigger.

You could also create a custom control with dependency properties if you want, to provide a more straightforward interface to this. For example:

public class ContentToggleButton : ToggleButton {
    public static readonly DependencyProperty UncheckedContentProperty =
        DependencyProperty.Register("UncheckedContent", typeof(object), typeof(ContentToggleButton));

    public object UncheckedContent {
        get { return GetValue(UncheckedContentProperty); }
        set { SetValue(UncheckedContentProperty, value); }
    }

    public static readonly DependencyProperty CheckedContentProperty =
        DependencyProperty.Register("CheckedContent", typeof(object), typeof(ContentToggleButton));

    public object CheckedContent {
        get { return GetValue(CheckedContentProperty); }
        set { SetValue(CheckedContentProperty, value); }
    }
}

Style for ContentToggleButton:

<Setter Property="Content" Value="{Binding RelativeSource={RelativeSource Mode=Self}, Path=UncheckedContent}" />
<Style.Triggers>
    <Trigger Property="IsChecked" Value="True">
        <Setter Property="Content" Value="{Binding RelativeSource={RelativeSource Mode=Self}, Path=CheckedContent}" />
    </Trigger>
</Style.Triggers>

Usage:

<local:ContentToggleButton>
    <local:ContentToggleButton.UncheckedContent>
        <Image Source="UncheckedImage.png" />
    </local:ContentToggleButton.UncheckedContent>
    <local:ContentToggleButton.CheckedContent>
        <Image Source="CheckedImage.png" />
    </local:ContentToggleButton.CheckedContent>
</local:ContentToggleButton>

This would also allow you to reassign the images through those properties without overriding the trigger.

Upvotes: 0

xr280xr
xr280xr

Reputation: 13282

You can use a style and triggers to accomplish it. I don't know if this is the best way, but it is an all XAML approach, which I like. Here's how I recently did the same thing:

<Style x:Key="ZoomToggleButton" TargetType="{x:Type ToggleButton}">
    <Setter Property="Content">
        <Setter.Value>
            <Image Source="/[my assembly];component/Resources/Images/Zoom_Out.png" Width="15" Height="15" Stretch="None" />
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ToggleButton}">
                <Border BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true" CornerRadius="4">
                    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsChecked" Value="true">
                        <Setter Property="Content">
                            <Setter.Value>
                                <Image Source="/[my assembly];component/Resources/Images/Zoom_In.png" Width="15" Height="15" Stretch="None" />
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

You could probably also do it without a custom ControlTemplate by just changing the value of the Content property using Style.Triggers.

Upvotes: 7

AgentFire
AgentFire

Reputation: 9780

You should use the style event triggers.

Make a style like this:

<Style TargetType="{x:Type ToggleButton}">
   ...
</Style>

Upvotes: 0

Related Questions