Search code examples
c#.netwpftogglebutton

change background toggle button


I try to change the background of a toggle button everytime when it is checked or not,using 2 pictures. At runtime, the toggle button is simple and I don't see any image. This is my code:

<Canvas Height="25" Name="canvas1" Width="186" Background="White">
    <ToggleButton Name="toggle1" Height="25" Padding="0" Width="27" Canvas.Left="131" Canvas.Top="0" BorderBrush="{x:Null}" Foreground="{x:Null}">

        <ToggleButton.Resources>
            <Style x:Key="OnOffToggleImageStyle" TargetType="ToggleButton">
            <Style.Triggers>
                <Trigger Property="IsChecked" Value="True">
                        <Setter Property="Background">
                            <Setter.Value>
                                <ImageBrush ImageSource="/WpfApp;component/Images/image1.png" Stretch="Uniform" TileMode="None" />
                            </Setter.Value>
                    </Setter>
                </Trigger>
                <Trigger Property="IsChecked" Value="False">
                    <Setter Property="Background">
                        <Setter.Value>
                                <ImageBrush ImageSource="/WpfApp;component/Images/image2.png" Stretch="Uniform" TileMode="None" />
                            </Setter.Value>
                    </Setter>
                </Trigger>
            </Style.Triggers>
        </Style>


Solution

  • Multiple things we can point here.

    • Firstly you're specifying the Style in ToggleButton.Resources with a x:Key. Thus it's not implicitly set. Setting a Style in resources of the item for which it applies in it's own scope is kinda weird. Rather just apply the Style directly as <ToggleButton.Style>.
    • Next, when working with Style.Triggers, make it a practice to specify a default Setter. This will prevent some headache for you. Also now instead of having two triggers for IsChecked=False/True, you only need one trigger as the other Background can be set as default.
    • Finally it seems like all you need from the ToggleButton is the IsChecked property and switch an Image. So just override the Template and provide a simple one yourself. This way you assure the behavior to stay consistent in all version of the OS and not rely on internal default template's working nicely for your customization(which wouldn't work in Windows-8 btw, what you're trying here for IsChecked=True due to internal overrides in default ControlTemplate)

    So putting this all together we get:

    <Style x:Key="MyToggleButtonStyle"
            TargetType="ToggleButton">
      <Setter Property="Background">
        <Setter.Value>
          <ImageBrush ImageSource="/WpfApp;component/Images/image2.png"
                      Stretch="Uniform"
                      TileMode="None" />
        </Setter.Value>
      </Setter>
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="ToggleButton">
            <Border Width="{TemplateBinding Width}"
                    Height="{TemplateBinding Height}"
                    Background="{TemplateBinding Background}" />
          </ControlTemplate>
        </Setter.Value>
      </Setter>
      <Style.Triggers>
        <Trigger Property="IsChecked"
                  Value="True">
          <Setter Property="Background">
            <Setter.Value>
              <ImageBrush ImageSource="/WpfApp;component/Images/image1.png"
                          Stretch="Uniform"
                          TileMode="None" />
            </Setter.Value>
          </Setter>
        </Trigger>
      </Style.Triggers>
    </Style>
    

    and apply it to your ToggleButton

    <ToggleButton Name="toggle1" Height="25" Padding="0" Width="27" Canvas.Left="131" Canvas.Top="0" BorderBrush="{x:Null}" Foreground="{x:Null}" Style="{DynamicResource MyToggleButtonStyle}">
    

    you can ofc remove the Key in the Style and make it implicitly apply to "all" ToggleButton's within the scope of the Style definition if you choose to.