Archive for January, 2008

WPF ControlTemplate Trigger tip

January 5, 2008 2:11 am

I didn’t fully realize how ControlTemplate Triggers work (or don’t) until I solved a problem with a UserControl today, with the help of this post on the MSDN forums.

A Triggers’ EnterActions or ExitActions don’t seem to get fired when a UserControl is constructed. If you want, say, an animation in your control to start on a property change, you can put a BeginStoryboard element into a Trigger’s EnterActions and a reverse BeginStoryboard into the ExitActions.

But for the control to start out right at initialization you also need to have the right Setter element on the Trigger to set initial states (in addition to setting the opposite initial states on the elements to be animated/initialized.)

Here’s a tiny example:

 1 <UserControl> <!-- Namespaces omitted for brevity --> 
 2   <Grid> 
 3     <ToggleButton x:Name="Toggle"> 
 4       <ToggleButton.Template> 
 5         <ControlTemplate TargetType="{x:Type ToggleButton}"> 
 6           <Grid> 
 7             <!-- Initial opacity is 1 for the initially unchecked ToggleButton state. A trigger changes it to 0 for an initial checked state. --> 
 8             <Grid x:Name="HideMe" Opacity="1"> 
 9               <TextBlock Text="Hidden"/> 
10             </Grid> 
11             <!-- Other parts of the control go here --> 
12           </Grid> 
13           <ControlTemplate.Triggers> 
14             <Trigger Property="ToggleButton.IsChecked" Value="True"> 
15               <!-- This setter hides the desired element when the ToggleButton's initial state is checked --> 
16               <Setter TargetName="HideMe" Property="Opacity" Value="0"/> 
17               <Trigger.EnterActions> 
18                 <BeginStoryboard> 
19                   <Storyboard> 
20                     <DoubleAnimation BeginTime="00:00:00" Duration="00:00:00.05" Storyboard.TargetName="HideMe" Storyboard.TargetProperty="(UIElement.Opacity)" To="0" /> 
21                   </Storyboard> 
22                 </BeginStoryboard> 
23               </Trigger.EnterActions> 
24               <!-- ExitActions go here to make the Grid with the TextBlock visible again --> 
25             </Trigger> 
26           </ControlTemplate.Triggers> 
27         </ControlTemplate> 
28       </ToggleButton.Template> 
29     </ToggleButton> 
30   </Grid> 
31 </UserControl>

The ToggleButton contains a TextBlock in line 9 that I want hidden when the ToggleButton’s IsChecked state is True. The animation in line 18 takes care of doing that when the user interacts with the control, but when the control is initialized, I need the Setter in line 16 to hide the TextBlock initially if the ToggleButton is checked by default (through data binding, for example.)