I'm trying to create an animation where an icon (a xaml vector graphic on a Viewbox-wrapped Canvas) goes from having its text (TextBlock) beside it to underneath it.
I currently have the Viewbox and TextBlock in a Horizontally oriented StackPanel. I can change the orientation to vertical, but this is an instant change (not smoothly animated). I can also just set the position of the TextBlock with a TranslateTransform (which can be animated), but this is difficult to do in a reusable way (i.e. without hard-coding values).
Can anyone tell me if there is any WPF-centric way to animate the transition from horizontal to vertical orientation in a stack-panel? Or another way I haven't thought of to achieve the desired effect?
Thanks all!
There is a feature in Blend called FluidLayout that can do this.
In Blend
Create a new state group, set a transition duration and enable fluid layout.
Create two states one for horizontal, one for vertical.
You can then use a behaviour to toggle between them.
If you don't have Blend you can download the SDK which should have the required files Microsoft.Expression.Interactions and System.Windows.Interactivity. Add references to these and try the sample below.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:il="clr-namespace:Microsoft.Expression.Interactivity.Layout;assembly=Microsoft.Expression.Interactions"
xmlns:ic="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
x:Class="WpfApplication4.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Grid x:Name="LayoutRoot">
<VisualStateManager.CustomVisualStateManager>
<ic:ExtendedVisualStateManager/>
</VisualStateManager.CustomVisualStateManager>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="Orientation" ic:ExtendedVisualStateManager.UseFluidLayout="True">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="00:00:00.3000000"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Vertical"/>
<VisualState x:Name="Horizontal">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="stack" Storyboard.TargetProperty="(StackPanel.Orientation)">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Orientation.Horizontal}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackPanel x:Name="stack" Margin="8,49,8,8">
<Button Content="Button"/>
<Button Content="Button"/>
<Button Content="Button"/>
<Button Content="Button"/>
<Button Content="Button"/>
</StackPanel>
<Button HorizontalAlignment="Left" Margin="8,8,0,0" VerticalAlignment="Top" Width="97" Height="25" Content="H">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ic:GoToStateAction StateName="Horizontal"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Button HorizontalAlignment="Left" Margin="109,8,0,0" VerticalAlignment="Top" Width="97" Height="25" Content="V">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ic:GoToStateAction StateName="Vertical"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
</Window>
You can use a similar method to handle the item transition using states to move the elements or by changing Grid.Row,RowSpan,Col. You may need some code to tie everything together. I'm looking at a more elaborate sample I'll post if I sort out the issues.
Related
In one of the windows of my WPF application, the button width cannot be changed to smaller size whatever I do. I tried change the property of "width" in xaml, drag the button in designer, or pragmatically change it using c#. Even if I created a new button in that window, the width could only be changed to larger size but could not be changed to smaller size. Though there was no error or warning, none of the approaches successfully change the width. The weird thing was, I could change the height of the button smaller or larger easily by dragging, and in my other window, I can change the buttons width and height smaller or larger easily. I am using the same style for all the buttons in all the windows. If I drag the button, there will be no response of it unless I unlock the one of the litlle "knot" around it, but it will look like this:
The only thing is that I use a notification template for this window and there are some animation effects. But I didn't see any major difference between it and others. Here is the XAML code:
<Window x:Class="Timebreak.NotiWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Timebreak"
mc:Ignorable="d"
Title="TimeBreak" Height="450" Width="450"
WindowStyle="None" AllowsTransparency="True" Opacity="0.7" Background="#f9f9ff"
WindowStartupLocation="Manual" Left="0" Top="0">
<Grid>
<Button x:Name="button1" Content="OK" Margin="358,341,13,72" Click="Submit_Click" FontSize="16" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<RadioButton x:Name="radioButton" Content="Yes. I want to stand up and take a break for (minutes)" HorizontalAlignment="Left" Height="26" Margin="31,105,0,0" VerticalAlignment="Top" Width="368" Checked="radioButton_Checked" FontSize="14"/>
<RadioButton x:Name="radioButton1" Content="No. I don't want to stand up and take a break because" HorizontalAlignment="Left" Margin="31,206,0,0" VerticalAlignment="Top" FontSize="14" Checked="radioButton1_Checked"/>
<Slider x:Name="slider" HorizontalAlignment="Left" Height="23" Margin="40,136,0,0" VerticalAlignment="Top" Width="374" IsSnapToTickEnabled="True" ValueChanged="slider_ValueChanged" Maximum="30" Minimum="1" Cursor="Hand" AutoToolTipPlacement="TopLeft" Interval="29" IsMoveToPointEnabled="True" TickPlacement="BottomRight"/>
<!-- Animation -->
<Grid.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)">
<SplineDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="0:0:2" Value="1"/>
<SplineDoubleKeyFrame KeyTime="0:0:4" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<Grid.RenderTransform>
<ScaleTransform ScaleY="1" />
</Grid.RenderTransform>
</Grid>
Does ideas about it? Thanks in advance!
Does ideas about it?
You forgot to post the markup of the custom Style that you are obviously using but you could try to set the MinWidth property of the Button to 0:
<Button x:Name="button1" Content="OK" Margin="358,341,13,72" Click="Submit_Click" FontSize="16"
VerticalAlignment="Top" HorizontalAlignment="Left" MinWidth="0"/>
Please post your all relevants parts of your XAML markup and code if still cannot increase the width of the Button.
I'm trying to achieve the same animation than VS2012 setup window, autosizing and centering on every content size change in a nice animated way.
The problem is that it can't be done purely by code as I don't know the final window size (for what I rely on SizeToContent="WidthAndHeight"), but letting SizeToContent="WidthAndHeight" by it's own does not allow me to animate the transition
Is there any way to do it?
I think the simplest way to achieve this is to use custom visual states within your window class. I made a small test project that you can download here: https://dl.dropboxusercontent.com/u/14810011/ResizingWindow.zip
You need Visual Studio 2012 to execute it.
The Main Window XAML looks like this:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ResizingWindow"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
x:Name="Window" x:Class="ResizingWindow.MainWindow"
Title="MainWindow" Width="350" Height="300" WindowStyle="None" ResizeMode="NoResize" WindowStartupLocation="CenterScreen">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ExtendedStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.6">
<VisualTransition.GeneratedEasingFunction>
<CubicEase EasingMode="EaseOut"/>
</VisualTransition.GeneratedEasingFunction>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="TextBlock">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="Window">
<EasingDoubleKeyFrame KeyTime="0" Value="300"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Extended">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="Window">
<EasingDoubleKeyFrame KeyTime="0" Value="400"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="TextBlock">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions>
<RowDefinition Height="300"/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<Border Background="#FF6C6C6C">
<Grid>
<TextBlock HorizontalAlignment="Center" TextWrapping="Wrap" Text="Hey, I here is some really cool content." VerticalAlignment="Top" FontSize="32" FontFamily="Segoe UI Light" TextAlignment="Center" Margin="0,50,0,0"/>
<CheckBox Content="I want to see more" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,15" IsChecked="{Binding ShowAdditionalContent}">
<i:Interaction.Behaviors>
<ei:DataStateBehavior Binding="{Binding ShowAdditionalContent}" Value="False" TrueState="Normal" FalseState="Extended"/>
</i:Interaction.Behaviors>
</CheckBox>
<Button Content="" HorizontalAlignment="Right" VerticalAlignment="Top" FontFamily="Segoe UI Symbol" FontSize="21.333" Style="{DynamicResource ButtonStyle}" Margin="0,5,5,0" Click="CloseMainWindow"/>
</Grid>
</Border>
<Border Grid.Row="1" Background="#FF383838">
<TextBlock x:Name="TextBlock" TextWrapping="Wrap" Text="You can see this, when the check box is activated." FontFamily="Segoe UI Light" FontSize="18.667" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Silver"/>
</Border>
</Grid>
</Window>
The aspects you have to notice are the following:
The main window consists of a grid whose second row is hidden by default. This is achieved by setting the window height to 300 while the grid actually uses 400 logical units. One could also calculate this height dynamically during runtime, but for this simple example, this is not necessary.
The second row becomes visible when the "Extended" visual state is activated. This is actually done using the check box which updates the corresponding view model and the attached DataStateBehavior (this is part of the Blend SDK) that responds to it. When the state is changed, this behavior ensures that the corresponding visual state is activated, i.e. "Normal" when the checkbox is unchecked and "Extended" when it is checked.
The WindowStyle is set to None and the ResizeMode is set to NoResize. This ensures that no border is shown around the window. There is also the option to set AllowTransparency to true but I wouldn't recommend that as this has some serious performance implications. Notice that the default Minimize, Maximize/Restore and Quit buttons will not be present in this modus, too.
Please feel free to ask if you have further questions.
I have what seems to be a fairly simple scenario that I am trying to implement in Silverlight, but despite all the incredibly powerful transitions functionality in Silverlight/Blend 4, I just cannot work out how to do it.
I have a layout that boils down to this:
<UserControl>
<Grid>
<StackPanel>
<Button x:Name="Button1" />
<Button x:Name="Button2" />
<Button x:Name="Button3" />
<Button x:Name="Button4" />
</StackPanel>
<Grid x:Name="Page1" />
<Grid x:Name="Page2" />
<Grid x:Name="Page3" />
<Grid x:Name="Page4" />
</Grid>
</UserControl>
At first, all four page grids are hidden and scaled to zero size, but when you click its corresponding button, the page should appear with a growing animation. When you click another button, the previous page should disappear with a shrinking animation, and another page should appear with a growing animation. In this way, you can use the buttons to go between all four pages.
The "right" way to do this, from what I've read, is to use visual states on the user control. So I created four states, Page1 to Page4, and for each state set the appropriate page grid to display. I then put commands on the buttons to change the visual state of the user control. This worked fine, and I could switch between the pages, but when I started trying to define the animations between the states I had problems.
At first, I thought I could define a 'To *' and 'From *' animation for each state. So when you were in state Page1, and clicked on the button to go to state Page2, it would play the 'From *' animation hiding Page1, then a 'To *' animation displaying Page2. But this doesn't work. Even if you have defined a 'To *' and 'From *' animation for each state, Silverlight only plays the 'To *' animation, and completely ignores the 'From *' animation!
Even worse, it seems this behaviour is how Silverlight is supposed to work, even though it makes no sense at all! It means if I want to have each page shrink and then another page grow in its place, I would have to define a separate transition from each state to each other state! For my current four pages, this would mean twelve separate transitions, but when I want to increase the number of pages, this number will shoot up. Ten pages would require 9*9 = 81 transitions! All to get the current page to shrink, and the new page to grow.
I can't believe this there isn't a better way to handle what seems to be such a simple scenario, but nothing I can find seems to say how. I could probably hack it together using codebehind that modifies storyboards, but I want to allow viewing and editing the page grids in Blend, and also everything I read says to avoid using codebehind and use View Models and visual states to handle things
Please tell me I'm missing something obvious?
In Blend, you just click on the state in the States tab to start state recording, define what the state should look like, and set the state transition duration.
You shouldn't have to worry about each individual state transition permutation, unless you wanted each one to be different.
If your states use properties that can't be "linearly" animated (like changing Visibility), check the FluidLayout button.
Edit:
You can create the "complete shrink and then grow" effect you describe using only one additional storyboard per state -- the Any -> {State} transition, setting the BeginTime to delay before growing the current element.
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
mc:Ignorable="d"
x:Class="CommandingLeakWithScrollbar.UserControl1"
d:DesignWidth="640" d:DesignHeight="480">
<Grid x:Name="LayoutRoot">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="VisualStateGroup">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:1"/>
<VisualTransition GeneratedDuration="0:0:1" To="Page1">
<Storyboard>
<DoubleAnimation BeginTime="0:0:1" Duration="0:0:1" To="640" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="grid1" d:IsOptimized="True" />
<DoubleAnimation BeginTime="0:0:1" Duration="0:0:1" To="480" Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="grid1" d:IsOptimized="True"/>
</Storyboard>
</VisualTransition>
<VisualTransition GeneratedDuration="0:0:1" To="Page2">
<Storyboard>
<DoubleAnimation BeginTime="0:0:1" Duration="0:0:1" To="640" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="grid2" d:IsOptimized="True" />
<DoubleAnimation BeginTime="0:0:1" Duration="0:0:1" To="480" Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="grid2" d:IsOptimized="True"/>
</Storyboard>
</VisualTransition>
<VisualTransition From="None" GeneratedDuration="0:0:1" To="Page1"/>
<VisualTransition From="None" GeneratedDuration="0:0:1" To="Page2"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="None"/>
<VisualState x:Name="Page1">
<Storyboard>
<DoubleAnimation Duration="0" To="640" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="grid1" d:IsOptimized="True" />
<DoubleAnimation Duration="0" To="480" Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="grid1" d:IsOptimized="True" />
</Storyboard>
</VisualState>
<VisualState x:Name="Page2">
<Storyboard>
<DoubleAnimation Duration="0" To="640" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="grid2" d:IsOptimized="True"/>
<DoubleAnimation Duration="0" To="480" Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="grid2" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="grid1" Background="Beige" Width="40" Height="40" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Grid x:Name="grid2" HorizontalAlignment="Right" Width="40" Height="40" VerticalAlignment="Top" Background="Wheat" />
<Grid HorizontalAlignment="Left" Width="40" Height="40" VerticalAlignment="Bottom" />
<Grid HorizontalAlignment="Right" Width="40" Height="40" VerticalAlignment="Bottom"/>
<StackPanel HorizontalAlignment="Center">
<Button Content="Reset" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:GoToStateAction StateName="None"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Button Content="Page1" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:GoToStateAction StateName="Page1"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Button Content="Page2" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:GoToStateAction StateName="Page2"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</StackPanel>
</Grid>
I'm hoping what I'm trying to do is possible using Visual States...
What I want to do is have a button that toggles a stackPanel between two states: 'In' and 'Out'. I would then call VisualStateManager.GoToState on the button's click event, to toggle between the two states.
The problem I've run into is I can't figure out how to attach states to the StackPanel. It won't let me using Expression Blend. So I'm stuck... Is there anyway to animate in and out this panel using VisualStateManager? (I know I could use Storyboards and create and In and Out animation, but I'd preffer to use States if possible)
I really hope this is possible. Otherwise what is VisualStateManager good for besides doing gimmicky rollover effects on buttons?
Thanks for any help!
just fired up Blend and got this:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
x:Class="WpfApplication1.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<StackPanel x:Name="LayoutRoot">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="PanelState">
<VisualState x:Name="In"/>
<VisualState x:Name="Out">
<Storyboard>
<ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)" Storyboard.TargetName="stackPanel">
<EasingThicknessKeyFrame KeyTime="0" Value="-65,15,0,0"/>
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<i:Interaction.Behaviors>
<ei:DataStateBehavior Binding="{Binding IsChecked, ElementName=toggleButton}" Value="True" TrueState="In" FalseState="Out"/>
</i:Interaction.Behaviors>
<Button Content="Button" Width="50" HorizontalAlignment="Left" Click="Button_Click"/>
<StackPanel x:Name="stackPanel" Height="100" HorizontalAlignment="Left" Margin="0,15,0,0">
<TextBlock><Run Text="Funnytext"/></TextBlock>
</StackPanel>
<ToggleButton x:Name="toggleButton" Content="Toggle" Width="50" HorizontalAlignment="Left"/>
</StackPanel>
</Window>
and code behind:
private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
{
var sgs=VisualStateManager.GetVisualStateGroups(LayoutRoot);
var sg=sgs[0] as VisualStateGroup;
VisualStateManager.GoToElementState(LayoutRoot, ((VisualState) sg.States[sg.CurrentState == sg.States[0]?1:0]).Name,true);
}
(didn't know what stackpanel you meant so i just included two)
EDIT: my bad, didn't notice I didn't include the clickhandler. For for your convenience I included an example to use a Togglebutton to toggle the states...
I have this controltempalte + trigger stuff in my WPF application.
<ControlTemplate TargetType="me:MyControl" x:Key="fade">
<ContentPresenter - other stuff />
<ControlTemplate.Triggers>
<Trigger Property="IsTransitioned" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation -<stuff>- />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
This works cool in WPF, and is very intuitive too for me to write this based on trigger as above.
When i port this to Silverlight (3), i am told i have to use VSM, states and groups etc. since triggers on control template is not supported.
I h ave looked at some samples, and i even atempted to apply teh VSM bits in, in the place of trigger as above, but can't get it to work.
Someone suggested to me that apart from VSM in the xaml, i will have to handle some events etc.
SL3 model is just being painful for me. Please help.
Silverlight 3 introduced interaction triggers which as far as I can tell do what you want but are a little more complex. There's very few examples about them out yet though.
If you're doing this manually you need references to System.Windows.Interactivity and Microsoft.Expression.Interactions (from Blend 3, the class will be in your references tab if you've installed it).
If you add the triggers in Blend then it will add those automatically. This is called Behaviours in Silverlight 3 and you will find these in Blend in the Behaviours section of the Assets tab.
An example of how they work. Note the storyboard sitting in the resource of the second rectangle, I couldn't get it to work inside the ControlStoryboardAction.Storyboard, but it did work if I made the rectangle a ContentControl and put it in the Template. This may be a bug or me missing something :
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Class="SLTrigger.MainPage"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ic="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
xmlns:im="clr-namespace:Microsoft.Expression.Interactivity.Media;assembly=Microsoft.Expression.Interactions">
<Grid x:Name="LayoutRoot">
<StackPanel>
<Rectangle Margin="5" Fill="Blue" Width="200" Height="100">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<ic:ChangePropertyAction PropertyName="Fill" Duration="0">
<ic:ChangePropertyAction.Value>
<SolidColorBrush Color="Red"/>
</ic:ChangePropertyAction.Value>
</ic:ChangePropertyAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
<Rectangle Margin="5" x:Name="AnimatedRectangle2" Fill="Blue" Width="200" Height="100">
<Rectangle.Resources>
<Storyboard x:Key="AnimationStoryboard">
<ColorAnimation
Storyboard.TargetName="AnimatedRectangle2"
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
To="Red"
AutoReverse="True"
Duration="0:0:0.5" />
</Storyboard>
</Rectangle.Resources>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<im:ControlStoryboardAction ControlStoryboardOption="Play" Storyboard="{StaticResource AnimationStoryboard}">
<!--
Doesn't work, but does work inside control templates??
<im:ControlStoryboardAction.Storyboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="AnimatedRectangle2"
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
To="Red"
AutoReverse="True"
Duration="0:0:0.5" />
</Storyboard>
</im:ControlStoryboardAction.Storyboard>
-->
</im:ControlStoryboardAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
<ContentControl>
<ContentControl.Template>
<ControlTemplate>
<Rectangle Margin="5" x:Name="AnimatedRectangle3" Fill="Blue" Width="200" Height="100">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<im:ControlStoryboardAction ControlStoryboardOption="Play">
<im:ControlStoryboardAction.Storyboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="AnimatedRectangle3"
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
To="Red"
AutoReverse="True"
Duration="0:0:0.5" />
</Storyboard>
</im:ControlStoryboardAction.Storyboard>
</im:ControlStoryboardAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>
<TextBlock TextAlignment="Center" Text="Click the rectangles" />
</StackPanel>
</Grid>
</UserControl>
The class file has nothing in it:
using System.Windows.Controls;
namespace SLTrigger
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
}
}