Search code examples
c#wpfstylescontroltemplatedatatrigger

wpf: change a style DataTrigger to a ControlTemplate DataTrigger


I have a large ControlTemplate for a ToggleButton. I am trying to add a data trigger with no succes.

I have however manged to add it using a style, as shown below:

    <Window.Resources>
    <Style x:Key="toggleBtnStyle" TargetType="{x:Type ToggleButton}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=myProperty}" Value="true">
                <Setter Property="Content" Value="IS TRUE"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=myProperty}" Value="false">
                <Setter Property="Content" Value="IS FALSE"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

<ToggleButton Height="34" HorizontalAlignment="Left" x:Name="toggleBroadcast" Click="Button_Click" VerticalAlignment="Top" Width="133" Margin="180,0,0,0" Style="{DynamicResource toggleBtnStyle}"/>

Is there a way to add this to a Control Template? I have the following control template which is triggered on the IsChecked Property of the ToggleButton, I am trying to change it to the DataTrigger in the Style above, without success.

        <ControlTemplate x:Key="ClipBoardButton1" TargetType="{x:Type ToggleButton}">
        <Border BorderThickness="1,1,1,1" CornerRadius="1,1,1,1" BorderBrush="Black" Background="Black" >
            <Grid>
                <Border x:Name="BorderUp" BorderThickness="1,1,1,1" CornerRadius="1,1,1,1" Background="Blue"/>
                <Border x:Name="BorderDown" BorderThickness="1,1,1,1" CornerRadius="1,1,1,1" Opacity="0" Background="Aqua"/>
                <ContentPresenter x:Name="Contents" HorizontalAlignment="Center" VerticalAlignment="Center" Width="Auto" Margin="0,0,0,0"/>
            </Grid>
        </Border>

        <ControlTemplate.Resources>
            <Storyboard x:Key="ButtonDownTimeLine">
                <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="BorderDown" Storyboard.TargetProperty="Opacity">
                    <SplineDoubleKeyFrame KeyTime="00:00:00.05" Value="1"/>
                </DoubleAnimationUsingKeyFrames>
                <ThicknessAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Contents" Storyboard.TargetProperty="Margin">
                    <SplineThicknessKeyFrame KeyTime="00:00:00.025" Value="0.5,0.5,0,0"/>
                </ThicknessAnimationUsingKeyFrames>
            </Storyboard>
            <Storyboard x:Key="ButtonUpTimeLine">
                <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="BorderDown" Storyboard.TargetProperty="Opacity">
                    <SplineDoubleKeyFrame KeyTime="00:00:00.25" Value="0"/>
                </DoubleAnimationUsingKeyFrames>
                <ThicknessAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Contents" Storyboard.TargetProperty="Margin">
                    <SplineThicknessKeyFrame KeyTime="00:00:00.25" Value="0,0,0,0"/>
                </ThicknessAnimationUsingKeyFrames>
            </Storyboard>
        </ControlTemplate.Resources>

        <ControlTemplate.Triggers>
            <Trigger Property="IsChecked" Value="True">
                <Trigger.EnterActions>
                    <BeginStoryboard Storyboard="{StaticResource ButtonDownTimeLine}"/>
                </Trigger.EnterActions>
                <Trigger.ExitActions>
                    <BeginStoryboard Storyboard="{StaticResource ButtonUpTimeLine}"/>
                </Trigger.ExitActions>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

To be clear:

  1. I want to use a DataTrigger on myProperty
  2. Have the same Trigger action as the IsChecked action currently. (Implement the Storyboards)

I have tried lots of different things and searched through so many posts, but cant find the answer I am seeking.

Can anyone tell me what I need to do ?


Solution

  • I guess, you are using a style to apply this Template to ToggleButton. If not, create a default style for ToggleButton and Set Template property to your ControlTemplate

    <Style TargetType="ToggleButton">
        <Setter Property="Template" Value="{StaticResource ClipBoardButton1}" />
    </Style>
    

    And, coming to your problem around using DataTriggers, I wouldn't add DataTriggers to ControlTemplate, because, think about this scenario, what happens when you want to use this same template at a different place where the property name is different (not myProperty)?

    To achieve what you are trying, you can update your Trigger in the ControlTemplate to the following:

    <Trigger Property="IsChecked" Value="True">
        <Setter Property="Content" Value="IS TRUE" />
        <Trigger.EnterActions>
            <BeginStoryboard Storyboard="{StaticResource ButtonDownTimeLine}"/>
        </Trigger.EnterActions>
        <Trigger.ExitActions>
            <BeginStoryboard Storyboard="{StaticResource ButtonUpTimeLine}"/>
        </Trigger.ExitActions>
    </Trigger>
    <Trigger Property="IsChecked" Value="False">
        <Setter Property="Content" Value="IS FALSE"></Setter>
    </Trigger>
    

    and Bind IsChecked property of ToggleButton to your myProperty

    <ToggleButton Height="34" HorizontalAlignment="Left" 
                  x:Name="toggleBroadcast" 
                  Click="Button_Click" 
                  VerticalAlignment="Top" 
                  Width="133" Margin="180,0,0,0" 
                  IsChecked="{Binding myProperty}"/>
    

    UPDATE

    Replace your trigger in ControlTemplate with:

    <DataTrigger Binding="{Binding myProperty}" Value="True">
        <DataTrigger.EnterActions>
            <BeginStoryboard Storyboard="{StaticResource ButtonDownTimeLine}"/>
        </DataTrigger.EnterActions>
        <DataTrigger.ExitActions>
            <BeginStoryboard Storyboard="{StaticResource ButtonUpTimeLine}"/>
        </DataTrigger.ExitActions>
    </DataTrigger>