locked
Can I make a visual State activate an animation or another visual state? Want to start an animation when a Certain Visual State is Activated RRS feed

  • Question

  • I want to simulate a group of circles bullseying in i.e. like radar honing in on a source / target... I have 6 circles growing outward.

    I want to simply change their opacities throughout the animation and the timeline... however, I only want this to start on once the visual state or a visual state is activated...

    So far I have been getting familiar with the Visual State Groups... but what I notice is that is more for... this one thing happens when this one thing is activated i.e. clicked or hovered over or entered...

    So I am thinking that the animation would need to be seperate but I am trying to figure / think of how i can get that animation to start at a specific time i.e. once a visual state is activated...

    thanks for the help...

    Friday, January 28, 2011 3:50 AM

Answers

  • Howdy,

    Sorry for all the confusion; clearly my fault for going off on a tangent in some ways.

    Please note that when I use the term "complex storyboard", I am referring to a Standard Storyboard and NOT a State Storyboard

     

    But, what I want to have happen is that lets say visualstate3 = 4 screen swipe and on that screen I want a certain animation to start.  i.e. once that swipe/visual state ends (on new screen) I want another animation to start. 

    The key area of complexity here is that you are saying - "once that swipe/visual state ends".

    Hooking up 2 Behaviours to a Button click event (i.e. GoToStateAction to activate the State, and ControlStoryboardAction to Begin your complex Storyboard) will begin both the simple State Storyboard and the complex Storyboard at the same time. Not when the State completes.

    For this scenario (on state end), you have no choice but to hook up the code on the State.Storyboard.Completed event.

     

    Now, I guess one way I can do it, and I don't know if it is the most efficient way is that I can set the button to do both the activate state and then also activate animation...

    As above, both simple and complex Storyboard will start at the same time. If this is sufficient, then absolutely take this option and no code required ;-).

     

    Generally, when we consider states, we consider that a state change can occur from many events and or scenarios (e.g. from code), and not just a button click, so this is why you see us all suggesting that you call the complex Storyboard.Begin() method in the coded event handler of the State Storyboard Completed event.

    This way you can be 100% that the complex Storyboard will always begin when that State finishes.

     

    I hope that clarifies the difference; please let us know if not. Happy to try and help!

     

    Cheers

     

     


    Expression MVP

    my blog : http://x-coders.com/blogs/sneaky/default.aspx

    • Marked as answer by Xtianus Sunday, January 30, 2011 9:32 PM
    Saturday, January 29, 2011 10:43 PM
    Moderator

All replies

  • Hello Xtianus,

    the problem is that there are no such build in events in the storyboard class. Storyboard.Begin() is a method and the only event on a storyboard is Completed event. So you have to create a workaround for your own custom events to interact with the timeline of a storyboard. A workaround because storyboard class is not inheritable.

    I wrote a helper class which provides additional events for a Silverlight storyboard (StoryboardEventHelper class). You can download it here at the Expression Gallery. Please note that it was written in VB. So if you are using VB as your programming language you might be lucky using my helper class. If you are using C# you would have to translate it to C#.

    The StoryboardEventHelper class provides two events:

    1) OnStoryboardStarted event - fires, when the stoyboard has started

    2) OnStoryboardPositionChanged event - fires each 10 milliseconds over the timeline of a running storyboard

    You can use this class even with the storyboard of a VisualState.

    About building this class I wrote an article on my blog (please use the MS Translator widget implemented on my blog in order to read the article in the language of your choice).

    Friday, January 28, 2011 9:10 AM
  • Visual states already start a storyboard when they are activated.  Usually the storyboard only has one keyframe, but you can make the state storyboard longer and more complex by clicking the expand timeline button to the right of your state name in the Objects and Timeline pane.

     

    Friday, January 28, 2011 8:20 PM
  • Howdy,

    I wrote about this in my soon to be released book on Expression Blend 4... here is an extract from chapter 10 explaining it and a sample of how to make it work..

     

     

     

    Managing State animations with Storyboards

    You have already used States throughout this book with simple changes to element properties in Chapter 8 “Working with States” and so now with your new found skills in working with the Storyboard, you will visit two State scenarios that will make more sense than if previously explained.

    There are several reasons why you would use States to fire an animation rather than calling a Storyboard directly. The only problem is that you can’t call a Storyboard directly from a State change.

    I know what you are thinking right now – “Doesn’t a State have a Storyboard by default?” The answer is yes it does, but it is a special Storyboard that only works on the first KeyFrame position of 0.000. In other words, the timeline has no effect against the Transition time of the State and a collection of KeyFrames will be ignored, limiting what can be animated.

    The following demonstrates a particular solution around this concept.

    1.       Create a new Silverlight Application + Website solution

    2.       Add a new Rectangle element to the top left of the artboard

    3.       Set the size of the Rectangle to approximately 150 x 150

    4.       Open the States panel

    5.       Create a new State called State1

    6.       Ensure Transition preview is turned ON as shown in figure 11.32

    7.       Set the Default transition to 0.1 second.

    8.       Select State1 in the States panel to begin recording

    9.       With the Rectangle element selected, open the Properties panel. Record the current value of the Visibility property.

     

    >>NOTE

    Why Record a property that won’t change?

    You need to have a recorded value in the State Storyboard for it to be valid and to fire the Completed event shortly. You also need a Transition time specified in order for the Storyboard to run.

     

     

    10.   Select the Base state

    11.   Open the Objects and Timeline panel

    12.   Create a new Storyboard named StateFired

    13.   Move the Playhead to 2.000

    14.   Drag the Rectangle element to the top right of the artboard and just for fun change the Y value of the Rotation Projection property located in the Transform category

    15.   Run the animation to make sure it works

    16.   Add a new Button element to the artboard and change its content to Play

    17.   Open the Behaviors category of the Asset panel

    18.   Find and drag the GoToStateAction behavior onto the button

    19.   Set the StateName property to State1 as you are calling the state in this sample and not the Storyboard

    20.   Open the code-behind file for MainPage.xaml either in Visual Studio or directly in Expression Blend

    21.   Write the following code directly into the constructor as highlighted in figure 11.33

    Listing 11.1 shows the State Storyboard Completed event calling the normal Storybaord.Begin() method

    namespace SilverlightApplication

    {

           public partial class MainPage : UserControl

           {

                  public MainPage()

                  {

                         // Required to initialize variables

                         InitializeComponent();

     

                State1.Storyboard.Completed += delegate(object sender, EventArgs e) { StateFired.Begin(); };

            }

           }

    }

     

     

     

     

    So the solution here is to create a trick state really, one that will fire a completed event allowing you to call the Begin() method on a standard storyboard.

     

    If this little snippet isn't clear enough, let me know and I will give you access to the entire chapter in its current pre-print state.

    HTH

     

    Cheers

     

     

     



    Expression MVP

    my blog : http://x-coders.com/blogs/sneaky/default.aspx

    Friday, January 28, 2011 11:19 PM
    Moderator
  • Hello Brennon,

    concerning your Note between 9. and 10.: The "default" storyboard of a VisualState is Nothing from the Code behind perspective as long as it is empty. So, is it correct to call it a ("default") storyboard?

    Best regards,

    Martin

    Saturday, January 29, 2011 7:31 AM
  • Howdy Martin,

    You are correct, and as you say a State doesn't contain a Storyboard by default until a KeyFrame is added so I can see how that is misleading, especially when it is out of context with the rest of the chapters that it refers to. Conceptually it appears as though there is a Storyboard by default - technically there is not.

    The Third paragraph is changed to read:

    I know what you are thinking right now – “When I modify a State, doesn’t it create a Storyboard by default?” The answer is yes it does, but it is a special Storyboard…

     

    The note should also read:

    >>NOTE

    Why Record a property that won’t change?

    You need to have a recorded value in the State Storyboard for it to be created and therefore able to fire the Completed event, which you will use shortly. In the case of States, Storyboards are not created by default until you modify an element property and Blend creates the Storyboard for you attached to the State.

     You also need a Transition time specified in order for the Storyboard to run.

     

    I hope my tech editors are as eagle eyed as you Martin ;-) They are editing it now.

    Thanks for pointing that out. Let me know if that makes more sense.

    Cheers

     


    Expression MVP

    my blog : http://x-coders.com/blogs/sneaky/default.aspx

    Saturday, January 29, 2011 10:20 AM
    Moderator
  • Hello Brennon,

    I guess, what I was writing in my previous reply wasn't even precise enough at all. The point that might be a little confusing is, that Blend 4 displays an empty place holder for a storyboard in the objects and timelime panel, as soon as the user is adding a new visual state to a visual state group. And I guess, Blend does this because it is a design tool.

    So maybe there are two perspectives that need to be distinguished:

    First perspective is the "Blend perspective". Its objective is to provide an intuitive interface that helps the user create a Storyboard. Therefore it provides an empty storyboard placeholder in the Blend UI after a new visual state has been added.

    Second perspective is the "Xaml perspective". This perspective is the real technical view that affects (even) the code behind.

    The differences between these two perspectives are visible on tracking the changes in xaml after each step to take in Blend to add a visual state. When you monitor the xaml changes after each step to take in Blend to add a visual state, there is no storyboard element in xaml until at least one keyframe was added to the timeline using Blend. When the user adds a keyframe using Blend by left-clicking the little oval symbol left of the display for the timeline position, Blend adds an empty storyboard to the xaml of the visual state but no keyframe:

    <VisualState x:Name="r1_DoNothing">

        <Storyboard/>

    </VisualState>

    And this little peace of xaml (the empty but not nothing storyboard) is enough to create a storyboard that fires the completed event. No further changes on any object property must be make!

    Here is an example:

    MainPage.xaml:

    <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"
           mc:Ignorable="d"
           x:Class="StoryboardsAndStatesLab.MainPage"
           Width="640"
           Height="480">
     <Grid Background="#FF87888B"
        Name="LayoutRoot">
      <VisualStateManager.VisualStateGroups>
       <VisualStateGroup x:Name="r1_States">
        <VisualState x:Name="r1_normal" />
        <VisualState x:Name="r1_DoNothing">
         <VisualState.Storyboard>
          <Storyboard />
         </VisualState.Storyboard>
        </VisualState>
        <VisualState x:Name="r1_DoSomething">
         <VisualState.Storyboard>
          <Storyboard>
           <DoubleAnimation Duration="0:0:1"
                    Storyboard.TargetName="r1"
                    Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)"
                    To="200" />
          </Storyboard>
         </VisualState.Storyboard>
        </VisualState>
       </VisualStateGroup>
      </VisualStateManager.VisualStateGroups>
      <Rectangle Fill="#FF6A5313"
            Height="102"
            HorizontalAlignment="Left"
            Margin="63,71,0,0"
            Name="r1"
            RenderTransformOrigin="0.5,0.5"
            Stroke="Black"
            VerticalAlignment="Top"
            Width="102">
       <Rectangle.RenderTransform>
        <CompositeTransform />
       </Rectangle.RenderTransform>
      </Rectangle>
     </Grid>
    </UserControl>
    

    MainPage.xaml.vb:

    Partial Public Class MainPage
    	Inherits UserControl
    
    	Public Sub New()
    		InitializeComponent()
    	End Sub
    
     Private Sub MainPage_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
      AddHandler r1_DoNothing.Storyboard.Completed, AddressOf MyRoutine
      VisualStateManager.GoToState(Me, "r1_DoNothing", True)
     End Sub
    
     Private Sub MyRoutine(ByVal sender As Object, ByVal e As EventArgs)
      VisualStateManager.GoToState(Me, "r1_DoSomething", True)
     End Sub
    
    End Class
    

    The above example has two states: The visual state "r1_DoNothing" has an empty but not nothing storyboard. The visual state "r1_DoSomething" has a storyboard that lets the rectangle r1 move from left to right. "r1_DoSomething" is activated when the completed event of the "r1_DoNothing" storyboard fires.

    Form the Blend perspective the storyboard of "r1_DoNothing" has one single keyframe. But from the "Xaml perspective" it actually doesn't have a single keyframe at all! From the "xaml perspective" it is just an empty but not nothing storyboard, ready to fire the Completed event.

    I hope this abstract representation, described from my personal point of view as I was trying to understand what is going on using Blend, is correct.

    Best regards,

    Martin

    Saturday, January 29, 2011 3:24 PM
  • Howdy Martin,

    Absolutely you are correct. The key here is that your r1_DoSomething storyboard is as complex as it can be for a State Storyboard. If you want to do anything further, you will need to call the Begin() method of a standard Storyboard.

    Good stuff!

    Cheers


    Expression MVP

    my blog : http://x-coders.com/blogs/sneaky/default.aspx

    Saturday, January 29, 2011 3:40 PM
    Moderator
  • I am trying to follow this as best I can... and it is me not you guys as I am really just learning all of this stuff. 

    From what both Kruger and Brennon are saying can the two explanations be simplified from a non code / Blend point of view...  Moreover, not to say Brennon's idea is more correct than the other, but since he is writing a book I though I'd ask his or kruger's explanation on what really is the best practice for the method I should be employing. 

    In other words, some of this went a little over my head... my fault of course.

    With that said let me explain it from my world and what I want / am trying to accomplish...

    I am working on a killer template for emulating a WP7 phone in SF... Apart of that emulation is the panoramic window that goes from left and or right. 

    In order to do this I have created buttons, left buttons and right buttons, for everytime I want to emulate the "thumb swipe" from side to side.  Now doing this i created visual states, (sorry the storyboard things loses me but probably because i a only working in SF), that = every visual state added is a new screen swipe going from right or left. 

    That works perfectly, and without any coding.

    But, what I want to have happen is that lets say visualstate3 = 4 screen swipe and on that screen I want a certain animation to start.  i.e. once that swipe/visual state ends (on new screen) I want another animation to start. 

    Now, I guess one way I can do it, and I don't know if it is the most efficient way is that I can set the button to do both the activate state and then also activate animation...

    For me that might be enough?

    You guys are experts so please let me know what I am thinking that is right or wrong and if something would be better ala like what you were explaining. 

     

    I super appreciate the help

    Saturday, January 29, 2011 9:09 PM
  • Hello Xtianus,

    are you asking from a more designer point of view, right?

    If so, starting a storyboard (an animation) when a visual state (swiping a Page) has ended would be a perfect task for a Blend behavior.

    At this moment I am writing from my phone so I will continue tomorrow.

    Saturday, January 29, 2011 10:43 PM
  • Howdy,

    Sorry for all the confusion; clearly my fault for going off on a tangent in some ways.

    Please note that when I use the term "complex storyboard", I am referring to a Standard Storyboard and NOT a State Storyboard

     

    But, what I want to have happen is that lets say visualstate3 = 4 screen swipe and on that screen I want a certain animation to start.  i.e. once that swipe/visual state ends (on new screen) I want another animation to start. 

    The key area of complexity here is that you are saying - "once that swipe/visual state ends".

    Hooking up 2 Behaviours to a Button click event (i.e. GoToStateAction to activate the State, and ControlStoryboardAction to Begin your complex Storyboard) will begin both the simple State Storyboard and the complex Storyboard at the same time. Not when the State completes.

    For this scenario (on state end), you have no choice but to hook up the code on the State.Storyboard.Completed event.

     

    Now, I guess one way I can do it, and I don't know if it is the most efficient way is that I can set the button to do both the activate state and then also activate animation...

    As above, both simple and complex Storyboard will start at the same time. If this is sufficient, then absolutely take this option and no code required ;-).

     

    Generally, when we consider states, we consider that a state change can occur from many events and or scenarios (e.g. from code), and not just a button click, so this is why you see us all suggesting that you call the complex Storyboard.Begin() method in the coded event handler of the State Storyboard Completed event.

    This way you can be 100% that the complex Storyboard will always begin when that State finishes.

     

    I hope that clarifies the difference; please let us know if not. Happy to try and help!

     

    Cheers

     

     


    Expression MVP

    my blog : http://x-coders.com/blogs/sneaky/default.aspx

    • Marked as answer by Xtianus Sunday, January 30, 2011 9:32 PM
    Saturday, January 29, 2011 10:43 PM
    Moderator
  • "Hooking up 2 Behaviours to a Button click event (i.e. GoToStateAction to activate the State, and ControlStoryboardAction to Begin your complex Storyboard) will begin both the simple State Storyboard and the complex Storyboard at the same time. Not when the State completes.

    For this scenario (on state end), you have no choice but to hook up the code on the State.Storyboard.Completed event."

    Perfect... This is exactly what I was looking for... I completely understand now. 

    One last thing.  Since I am a none coder / noob would you give a little bit more detailed instructions on how/where to implant the code... i.e. and for what files and perhaps to know if it is for every page that needs the functionality. 

    Thanks so much.

    Sunday, January 30, 2011 9:32 PM
  • Hello Xtanius,

    inspired by your question and especially from your designers perspective (the need to start a certain storyboard when another storyboard or a storyboard of a certain visual state has completed without having to code) I have created the StoryboardCompletedBehaviors. You can download them here a the Expression Gallery.

    The contribution contains one StoryboardCompletedAction to which you can assign either a StoryboardCompetedTrigger (in order to start one storyboard when another storyboard has completed) or a StateStoryboardCompletedTrigger (in order to start a storyboard when the storyboard of a certain visual state has completed).

    Please let me know if these behavior help you to solve your problem in your certain scenario. If not please feel free to post again here, so that I can customize the behavior appropriate to your needs.

    Best regards,

    Martin

    Monday, January 31, 2011 8:55 AM
  • wow... I really want to try this out to see how it works...

    as well, can you just clear up Story board vs. Visual state group vs. animations... I see the storyboard is were the object and timeline window is located but I don't think i am thinking of it correctly...

    Just so you know I am soley in SketchFlow as I am sort of forcing myself to learn in that areana first. 

    Thanks so much. 

    Monday, January 31, 2011 6:41 PM
  • Hello Xtanius,

    here is the link to the article on my blog about how to use my StoryboardCompletedBehaviors.

    Please comment on my blog if you have any question or suggestion on these behaviors.

    Best regards,

    Martin

    Tuesday, February 1, 2011 11:13 AM