locked
Change a property which is animated by an Storyboard RRS feed

  • Question

  • In my app I want to animate RenderTransform.X of the Grid from both a button click (in which case I'm calling a Storyboard in the page resources) and swipe gesture, where I'm changing the RenderTransform.X from code behind. Problem is once the Storyboard has run, change to the value from code-behind does not take effect. As the property is locked under the Animation!

    As per http://msdn.microsoft.com/en-us/library/aa970493.aspx I should

    1. Change FillBehaviour to Stop on the Animation.

    2. Remove entire storyboard

    3. Remove animation from individual property.

    None of these seem to be working for me, for following reasons.

    #1 Would stop (even) the storyboard from animating the X (it is doing rest of the animations though!)

    #2 Wouldn't work because Storyboard does not have Remove method.

    #3 would not work under WinRT because there is no BeginAnimation method, when I tried Storyboard.SetTarget(null, myGrid) I got an exception.

    Has someone come across this? help!

    thanks


    Sameer V.

    Tuesday, March 19, 2013 4:14 PM

Answers

  • I adapted your nice layout [updates in XAML and in C#] into a working solution as follows:

    <Page
        x:Class="App9.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App9"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
        <Page.Resources>
            <Storyboard x:Name="sbShowSidebar">
                <DoubleAnimation Storyboard.TargetName="LayoutRoot"
                              Storyboard.TargetProperty="(Grid.RenderTransform).(TranslateTransform.X)"
                              To="-320"
                              Duration="0:00:00.3"/>
            </Storyboard>
            <Storyboard x:Name="sbHideSidebar">
                <DoubleAnimation Storyboard.TargetName="LayoutRoot"
                                 Storyboard.TargetProperty="(Grid.RenderTransform).(TranslateTransform.X)"
                                 To="0"
                                 Duration="0:00:00.3"/>
            </Storyboard>
        </Page.Resources>
        <Grid Name="LayoutRoot" Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Grid.RenderTransform>
                <TranslateTransform X="0" Y="0"/>
            </Grid.RenderTransform>
            <Grid.RowDefinitions>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="320"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="auto"/>
            </Grid.ColumnDefinitions>
            <StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="1"
                        HorizontalAlignment="Right">
                <TextBlock Text="CODE BEHIND"
                           VerticalAlignment="Center"/>
                <Button Content="Hide" Name="btnHide" Click="btnHide_Click"/>
                <Button Content="Show" Name="btnShow"  Click="btnShow_Click"/>
    
                <TextBlock Text="STORYBOARD" Margin="100,0,0,0"
                           VerticalAlignment="Center"/>
                <Button Content="Hide" Name="btnSBHide" Click="btnSBHide_Click"/>
                <Button Content="Show" Name="btnSBShow"  Click="btnSBShow_Click"/>
            </StackPanel>
            <Border Name="pnlLeft" Background="Green" Grid.Column="0" Grid.Row="0" Grid.RowSpan="2"/>
            <Grid Name="gridMainContent" Grid.Column="1" Grid.Row="1"
                  Background="Brown">
            </Grid>
            <Border Name="borderSidebar" Grid.Column="2" Grid.Row="0" Grid.RowSpan="2"
                    Margin="0,0,-320,0" Width="320"
                    HorizontalAlignment="Right" VerticalAlignment="Stretch"
                    Background="SteelBlue"/>
        </Grid>
    </Page>

    ---

    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Media;
    
    namespace App9
    {
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
            }
    
            private void btnHide_Click(object sender, RoutedEventArgs e)
            {
                this.StopStoryboards();
                // Don't address by name the 'transform' because that creates a copy
                // that is reassigned to the Control. Next time, the StoryBoard
                // will retrieve its own original 'dangling' 'transform' reference which does
                // not belong to the Control anymore. Hence: 'nothing will happen'
                TranslateTransform tt = LayoutRoot.RenderTransform as TranslateTransform;
                tt.X = 0;
            }
    
            private void btnShow_Click(object sender, RoutedEventArgs e)
            {
                this.StopStoryboards();
                TranslateTransform tt = LayoutRoot.RenderTransform as TranslateTransform;
                tt.X = -320;
            }
    
            private void btnSBHide_Click(object sender, RoutedEventArgs e)
            {
                this.sbHideSidebar.Begin();
            }
    
            private void btnSBShow_Click(object sender, RoutedEventArgs e)
            {
                this.sbShowSidebar.Begin();
            }
    
            private void StopStoryboards()
            {
                if (this.sbShowSidebar.GetCurrentState() != Windows.UI.Xaml.Media.Animation.ClockState.Stopped) { this.sbShowSidebar.Stop(); }
                if (this.sbHideSidebar.GetCurrentState() != Windows.UI.Xaml.Media.Animation.ClockState.Stopped) { this.sbHideSidebar.Stop(); }
            }
        }
    }
    
    

    • Marked as answer by Sameer.V Wednesday, March 20, 2013 11:27 AM
    Wednesday, March 20, 2013 6:30 AM

All replies

  • Hi Sameer,

    The UI Design for Windows Store apps forum is for language agnostic discussion about designing the UI for Windows Store apps. For questions about implementing the UI please post in the appropriate language forum. Since it appears that your question is about using Xaml and C# or VB I'll move this to that forum for you.

    --Rob

    Tuesday, March 19, 2013 4:16 PM
    Moderator
  • Thanks Rob and sorry about the mess :-)


    Sameer V.

    Tuesday, March 19, 2013 4:21 PM
  • This example implements both Storyboard and direct property changes. Note to use "(UIElement.RenderTransform).(TranslateTransform.X)" on the storyboard. Hopefully, it helps in your scenario.

    <Page
        x:Class="AnimateCanvasTopLeft2.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:AnimateCanvasTopLeft2"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
        <Page.Resources>
            <Storyboard x:Key="sb">
                <DoubleAnimation Storyboard.TargetName="ellipse"
                 Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)"
                 From="0" To="600" Duration="0:0:5">
                </DoubleAnimation>
            </Storyboard>
        </Page.Resources>
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Canvas>
                <Ellipse Name="ellipse" Width="60" Height="60" Fill="Olive">
                    <Ellipse.RenderTransform>
                        <TranslateTransform X="400"/>
                    </Ellipse.RenderTransform>
                </Ellipse>
                <Button Content="Storyboard" Click="Button_Click_1" Canvas.Top="100"/>
                <Button Content="Direct" Click="Button_Click_2" Canvas.Top="200"/>
            </Canvas>
        </Grid>
    </Page>

    ---

    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Media.Animation;
    
    namespace AnimateCanvasTopLeft2
    {
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
                this.storyboard = this.Resources["sb"] as Storyboard;
            }
            Storyboard storyboard;
            private void Button_Click_1(object sender, RoutedEventArgs e)
            {
                if (storyboard.GetCurrentState() != ClockState.Stopped)
                    storyboard.Stop();
                storyboard.Begin();
            }
            private void Button_Click_2(object sender, RoutedEventArgs e)
            {
                if (storyboard.GetCurrentState() != ClockState.Stopped)
                    storyboard.Stop();
                TranslateTransform tt = ellipse.RenderTransform as TranslateTransform; 
                tt.X = 0;
            }
        }
    }
    

    Tuesday, March 19, 2013 5:40 PM
  • Hi,

    Thanks for replying but this solution did not work, reason being Storyboard.Stop() resets the TranslateTransform.X to the original value of 0.

    I wrote a simple app to test this scenario, and created buttons to change the TranslateTransform.X from code and storyboard and this revealed curious behaviour.

    Clicking Storyboard.SHOW
     Clicking Show (code behind) will change the X for the first time, but subsequently both CODEBEHIND.hide and CODEBEHIND.show wouldn't work.

    Clicking Storyboard.HIDE
     Now the Show (code behind) would always work but Hide will never work, unless I click Storyboard.Hide

    This is simplified version of my code which should describe the problem http://sdrv.ms/11fLQxO

    Interesting enough, when I ran your code (in a separate project) and commented the storyboard.Stop() call, code worked fine i.e. TranslateTransform.X changed from both the storyboard and code-behind.

    Hope this helps.

    Thanks


    Sameer V.

    Tuesday, March 19, 2013 8:28 PM
  • I adapted your nice layout [updates in XAML and in C#] into a working solution as follows:

    <Page
        x:Class="App9.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App9"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
        <Page.Resources>
            <Storyboard x:Name="sbShowSidebar">
                <DoubleAnimation Storyboard.TargetName="LayoutRoot"
                              Storyboard.TargetProperty="(Grid.RenderTransform).(TranslateTransform.X)"
                              To="-320"
                              Duration="0:00:00.3"/>
            </Storyboard>
            <Storyboard x:Name="sbHideSidebar">
                <DoubleAnimation Storyboard.TargetName="LayoutRoot"
                                 Storyboard.TargetProperty="(Grid.RenderTransform).(TranslateTransform.X)"
                                 To="0"
                                 Duration="0:00:00.3"/>
            </Storyboard>
        </Page.Resources>
        <Grid Name="LayoutRoot" Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Grid.RenderTransform>
                <TranslateTransform X="0" Y="0"/>
            </Grid.RenderTransform>
            <Grid.RowDefinitions>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="320"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="auto"/>
            </Grid.ColumnDefinitions>
            <StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="1"
                        HorizontalAlignment="Right">
                <TextBlock Text="CODE BEHIND"
                           VerticalAlignment="Center"/>
                <Button Content="Hide" Name="btnHide" Click="btnHide_Click"/>
                <Button Content="Show" Name="btnShow"  Click="btnShow_Click"/>
    
                <TextBlock Text="STORYBOARD" Margin="100,0,0,0"
                           VerticalAlignment="Center"/>
                <Button Content="Hide" Name="btnSBHide" Click="btnSBHide_Click"/>
                <Button Content="Show" Name="btnSBShow"  Click="btnSBShow_Click"/>
            </StackPanel>
            <Border Name="pnlLeft" Background="Green" Grid.Column="0" Grid.Row="0" Grid.RowSpan="2"/>
            <Grid Name="gridMainContent" Grid.Column="1" Grid.Row="1"
                  Background="Brown">
            </Grid>
            <Border Name="borderSidebar" Grid.Column="2" Grid.Row="0" Grid.RowSpan="2"
                    Margin="0,0,-320,0" Width="320"
                    HorizontalAlignment="Right" VerticalAlignment="Stretch"
                    Background="SteelBlue"/>
        </Grid>
    </Page>

    ---

    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Media;
    
    namespace App9
    {
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
            }
    
            private void btnHide_Click(object sender, RoutedEventArgs e)
            {
                this.StopStoryboards();
                // Don't address by name the 'transform' because that creates a copy
                // that is reassigned to the Control. Next time, the StoryBoard
                // will retrieve its own original 'dangling' 'transform' reference which does
                // not belong to the Control anymore. Hence: 'nothing will happen'
                TranslateTransform tt = LayoutRoot.RenderTransform as TranslateTransform;
                tt.X = 0;
            }
    
            private void btnShow_Click(object sender, RoutedEventArgs e)
            {
                this.StopStoryboards();
                TranslateTransform tt = LayoutRoot.RenderTransform as TranslateTransform;
                tt.X = -320;
            }
    
            private void btnSBHide_Click(object sender, RoutedEventArgs e)
            {
                this.sbHideSidebar.Begin();
            }
    
            private void btnSBShow_Click(object sender, RoutedEventArgs e)
            {
                this.sbShowSidebar.Begin();
            }
    
            private void StopStoryboards()
            {
                if (this.sbShowSidebar.GetCurrentState() != Windows.UI.Xaml.Media.Animation.ClockState.Stopped) { this.sbShowSidebar.Stop(); }
                if (this.sbHideSidebar.GetCurrentState() != Windows.UI.Xaml.Media.Animation.ClockState.Stopped) { this.sbHideSidebar.Stop(); }
            }
        }
    }
    
    

    • Marked as answer by Sameer.V Wednesday, March 20, 2013 11:27 AM
    Wednesday, March 20, 2013 6:30 AM
  • Worked like a charm! Thank you so much, really appreciate your help.


    Sameer V.

    Wednesday, March 20, 2013 11:27 AM