locked
Using expression blend states in Visual studio. RRS feed

  • Question

  • Hey guys,

    I just discovered expression blend and its ability to animate various UI objects using states, however I'm having some trouble using the animations in C#.
    At the moment I have a simple popup window which has to visible states (PopupHidden, PopupVisible), my understanding is that using expression blend you can choose when these states are called using triggers.
    However I would like to call forward these visual states based on an if statement.

    i.e.

    If(Settings["Setup"] == "true")
    {
    //popup remains hidden
    }
    else
    {
    //popup visible transition occurs
    }

    Unfortunately I have close to no idea how to handle this.
    My understanding is that one can use the Visualstatemanager somehow but upon using this code VisualStateManager.GoToState(this,"PopupVisible",true); I have had no luck, the setup window just overlays the mainpage regardless.

    Any help would be greatly appreciated with this issue.
    Sunday, October 2, 2011 1:50 PM

Answers

  • I had no problem at all. I created the following example during my train commute!

    First, I want to clarify that although people have been using the term "popup" in this thread, it was not referring to the Silverlight Popup control. My assumption is that people here were talking about using a Grid for popup-like effect.

    My steps were the following:
    1. Open a project and add a Grid that you want to behave like a popup.
    2. Open the project in Expression Blend.
    3. Select the Grid and add a visual state group.
    4. To the visual state group, add states OpenState and ClosedState
    5. For the OpenState, add a transition storyboard for OpenState-to-ClosedState. This storyboard changes the grid TranslateX from 0 to -480 and the Opacity from 1 to 0.
    6. For the ClosedState, set TranslateX=-480 and Opacity=0. Add a transition storyboard for ClosedState-to-OpenState. This storyboard changes the grid TranslateX from -480 to 0 and the Opacity from 0 to 1.
    7. Back in Visual Studio, initialize the grid to ClosedState and add buttons to move between the states.

    MainPage.xaml (everything under the VisualStateManager was generated by Expression Blend)
        <!--LayoutRoot is the root grid where all page content is placed--> 
        <Grid x:Name="LayoutRoot" Background="Transparent"
            <VisualStateManager.VisualStateGroups> 
                <VisualStateGroup x:Name="OpenStateGroup"
                    <VisualStateGroup.Transitions> 
                        <VisualTransition From="OpenState" GeneratedDuration="0" To="ClosedState"
                            <Storyboard> 
                                <DoubleAnimation Duration="0:0:1" To="-480" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="GridPopup"/> 
                                <DoubleAnimation Duration="0:0:1" To="0" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="GridPopup" d:IsOptimized="True"/> 
                            </Storyboard> 
                        </VisualTransition> 
                        <VisualTransition From="ClosedState" GeneratedDuration="0" To="OpenState"
                            <Storyboard> 
                                <DoubleAnimation Duration="0:0:1" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="GridPopup"/> 
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="GridPopup"
                                    <EasingDoubleKeyFrame KeyTime="0" Value="0"/> 
                                    <EasingDoubleKeyFrame KeyTime="0:0:1" Value="1"/> 
                                </DoubleAnimationUsingKeyFrames> 
                            </Storyboard> 
                        </VisualTransition> 
                    </VisualStateGroup.Transitions> 
                    <VisualState x:Name="OpenState"/> 
                    <VisualState x:Name="ClosedState"
                        <Storyboard> 
                            <DoubleAnimation Duration="0" To="-480" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="GridPopup" d:IsOptimized="True"/> 
                        </Storyboard> 
                    </VisualState> 
                </VisualStateGroup> 
            </VisualStateManager.VisualStateGroups> 
            <Grid.RowDefinitions> 
                <RowDefinition Height="Auto"/> 
                <RowDefinition Height="*"/> 
            </Grid.RowDefinitions> 
     
            <!--TitlePanel contains the name of the application and page title--> 
            <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"
                <TextBlock x:Name="ApplicationTitle" Text="GRID VISUAL STATES" Style="{StaticResource PhoneTextNormalStyle}"/> 
                <TextBlock x:Name="PageTitle" Text="Visual States" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> 
            </StackPanel> 
     
            <!--ContentPanel - place additional content here--> 
            <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" RenderTransformOrigin="0.5,0.5"
                <Button x:Name="OpenButton" Content="go to OpenState" Click="OpenButton_Click" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
            </Grid> 
             
            <Grid x:Name="GridPopup" Background="DarkBlue" RenderTransformOrigin="0.5,0.5" Grid.RowSpan="2"
                <Grid.RenderTransform> 
                    <CompositeTransform/> 
                </Grid.RenderTransform> 
                <Button x:Name="CloseButton" Content="go to ClosedState" Click="CloseButton_Click" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
            </Grid> 
        </Grid> 

    MainPage.xaml.cs
        public partial class MainPage: PhoneApplicationPage 
        { 
            public MainPage() 
            { 
                InitializeComponent(); 
     
                VisualStateManager.GoToState(this"ClosedState"false); 
            } 
     
            private void CloseButton_Click(object sender, RoutedEventArgs e) 
            { 
                VisualStateManager.GoToState(this"ClosedState"true); 
            } 
     
            private void OpenButton_Click(object sender, RoutedEventArgs e) 
            { 
                VisualStateManager.GoToState(this"OpenState"true); 
            } 
        } 


    Richard Woo

    Tuesday, October 4, 2011 6:13 PM

All replies

  • If you want to abruptly show/hide your Popups in code behind, put in your if/else,

     

    Show;

     

                yourPopUp.Visibility = System.Windows.Visibility.Visible;

                yourPopUp.IsOpen = true;

     

    Hide;

     

                yourPopUp.Visibility = System.Windows.Visibility.Collapsed;

                yourPopUp.IsOpen = false;

     

    If you want to gradually show/hide them take a look at using storyboards on the opacity property.

    Sunday, October 2, 2011 2:58 PM
  • I used expression to give the popup visual states.

    PopupVisible (The popup fades in whilst sliding in from the left)
    PopupHidden (The Popup fades out whilst sliding to the right).

    This is what I want to activate within visual studio.
    Sunday, October 2, 2011 3:25 PM
  • Ok, I would do it all in code behind since most of the eye candy I do requires code behind anyway. Don’t do much Blend except for setting up the visual controls.

     

    In code behind I would use;  myStoryBoard.Begin(); so I am guessing if you named your storyboards in xaml , try that in your if/else.

     

    Maybe someone who uses Blend more can help you out.

    Sunday, October 2, 2011 6:53 PM
  • Naming the storyboard I mentioned above using templates won’t do anything. Don’t know if this will help you, but I did some concept code as a learning exercise.

     

    Not a Blend expert and never tried control templates. Never had a requirement to use them, but they do look like a simple way to spiffy up a control.

     

    Anyway, you may have been very close in your use of VisualStateManager.GoToState. Try changing “this” to the name of your popup. If you didn’t name it in blend, name it.

     

                VisualStateManager.GoToState(yourPopUp, "yourVisualState", true);

     

    Monday, October 3, 2011 12:16 AM
  • the popup is a grid, so when i change this to SetupWindow I get Error 

     Argument 1: cannot convert from 'System.Windows.Controls.Grid' to 'System.Windows.Controls.Control' 
    Monday, October 3, 2011 11:10 AM
  • Looks like the VisualStateManager only works on controls. The testing I did was on a Button, sorry about that. Did some further experimenting with a grid and using states to control the background color and was successful in code behind.

     

    Not sure what your xaml looks like, mine is hacked. I actually created it by coping the VisualStateManager from the button into a grid in VS xaml, not using Blend. Then modifying it.

     

    Firing the storyboard is the key to do this in code behind, so give this a try, it worked on a grid color transition;

     

                myVisualStateName.Storyboard.Begin();

     

    Which I guess is PopupHidden, PopupVisible. If not look at your xaml, and use or name the xaml VisualState;

     

                <VisualState x:Name="myVisualStateName" >

     

    Hopefully that should do it, if not post your xaml. Interesting learning experience, I may try more complicated animations doing them in Blend and controlling them from code behind. May save some coding time
    Monday, October 3, 2011 2:40 PM
  • you need to change VisualStateManager.GoToState(yourPopUp, "yourVisualState"true); to VisualStateManager.GoToState(this, "yourVisualState"true);


    States are for the main window of a silverlight page or a custom control.  If you are showing a popup which is a grid with a couple of objects  inside, then the Grid lies within the LayoutRoot which is your main window.  in this instance then VisualStateManager.GoToState(this, "yourVisualState"true); will work.

    If you are styling a control like a textbox and add more states, then you will need to derive from the textbox class to make your own custom controls and have the VisualStateManager.GoToState(this, "yourVisualState"true); in the custom control .cs file on specific events.
    Monday, October 3, 2011 3:15 PM
  • Firing the storyboard is the key to do this in code behind, so give this a try, it worked on a grid color transition;

     

                myVisualStateName.Storyboard.Begin();

    If you're going to launch the storyboard explicitly, then you may as well manage everything yourself and not use visual states at all. The whole point about visual states is that you can switch between states by simply calling GoToState(), and the transition storyboards and layout changes happen automatically.



    Richard Woo

    Monday, October 3, 2011 4:09 PM
  • The whole point about visual states is that you can switch between states by simply calling GoToState(), and the transition storyboards and layout changes happen automatically.


    Richard, I agree but the OP couldn’t get it work on a grid. I would normally do everything in code behind if I wanted to slide a panel on and off screen.

     

    So for a quick test I hacked some xaml using a grid and adding a VisualStateManager, and was able to access the storyboards for color transitions. Don’t know about move translations. Not really sure how the xaml would look creating this in blend on a grid. Probably an example of translation animations on a grid would be helpful.

     

    So how do you use GoToState() on a grid? The OP tried it and I tried it. Couldn’t get it to work, “cannot convert from 'System.Windows.Controls.Grid' to 'System.Windows.Controls.Control'.

     

    Monday, October 3, 2011 5:45 PM
  • The whole point about visual states is that you can switch between states by simply calling GoToState(), and the transition storyboards and layout changes happen automatically.


    Richard, I agree but the OP couldn’t get it work on a grid. I would normally do everything in code behind if I wanted to slide a panel on and off screen.

     

    So for a quick test I hacked some xaml using a grid and adding a VisualStateManager, and was able to access the storyboards for color transitions. Don’t know about move translations. Not really sure how the xaml would look creating this in blend on a grid. Probably an example of translation animations on a grid would be helpful.

     

    So how do you use GoToState() on a grid? The OP tried it and I tried it. Couldn’t get it to work, “cannot convert from 'System.Windows.Controls.Grid' to 'System.Windows.Controls.Control'.

     



    If there is a simple way to use GoToState() on a grid I would love to hear it. (Although I can guess I may have to convert it to a Usercontol or control in blend)

    I will attempt to use storyboard (although atm im not on my desktop at the moment).

    Tuesday, October 4, 2011 5:25 PM
  • I had no problem at all. I created the following example during my train commute!

    First, I want to clarify that although people have been using the term "popup" in this thread, it was not referring to the Silverlight Popup control. My assumption is that people here were talking about using a Grid for popup-like effect.

    My steps were the following:
    1. Open a project and add a Grid that you want to behave like a popup.
    2. Open the project in Expression Blend.
    3. Select the Grid and add a visual state group.
    4. To the visual state group, add states OpenState and ClosedState
    5. For the OpenState, add a transition storyboard for OpenState-to-ClosedState. This storyboard changes the grid TranslateX from 0 to -480 and the Opacity from 1 to 0.
    6. For the ClosedState, set TranslateX=-480 and Opacity=0. Add a transition storyboard for ClosedState-to-OpenState. This storyboard changes the grid TranslateX from -480 to 0 and the Opacity from 0 to 1.
    7. Back in Visual Studio, initialize the grid to ClosedState and add buttons to move between the states.

    MainPage.xaml (everything under the VisualStateManager was generated by Expression Blend)
        <!--LayoutRoot is the root grid where all page content is placed--> 
        <Grid x:Name="LayoutRoot" Background="Transparent"
            <VisualStateManager.VisualStateGroups> 
                <VisualStateGroup x:Name="OpenStateGroup"
                    <VisualStateGroup.Transitions> 
                        <VisualTransition From="OpenState" GeneratedDuration="0" To="ClosedState"
                            <Storyboard> 
                                <DoubleAnimation Duration="0:0:1" To="-480" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="GridPopup"/> 
                                <DoubleAnimation Duration="0:0:1" To="0" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="GridPopup" d:IsOptimized="True"/> 
                            </Storyboard> 
                        </VisualTransition> 
                        <VisualTransition From="ClosedState" GeneratedDuration="0" To="OpenState"
                            <Storyboard> 
                                <DoubleAnimation Duration="0:0:1" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="GridPopup"/> 
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="GridPopup"
                                    <EasingDoubleKeyFrame KeyTime="0" Value="0"/> 
                                    <EasingDoubleKeyFrame KeyTime="0:0:1" Value="1"/> 
                                </DoubleAnimationUsingKeyFrames> 
                            </Storyboard> 
                        </VisualTransition> 
                    </VisualStateGroup.Transitions> 
                    <VisualState x:Name="OpenState"/> 
                    <VisualState x:Name="ClosedState"
                        <Storyboard> 
                            <DoubleAnimation Duration="0" To="-480" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="GridPopup" d:IsOptimized="True"/> 
                        </Storyboard> 
                    </VisualState> 
                </VisualStateGroup> 
            </VisualStateManager.VisualStateGroups> 
            <Grid.RowDefinitions> 
                <RowDefinition Height="Auto"/> 
                <RowDefinition Height="*"/> 
            </Grid.RowDefinitions> 
     
            <!--TitlePanel contains the name of the application and page title--> 
            <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"
                <TextBlock x:Name="ApplicationTitle" Text="GRID VISUAL STATES" Style="{StaticResource PhoneTextNormalStyle}"/> 
                <TextBlock x:Name="PageTitle" Text="Visual States" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> 
            </StackPanel> 
     
            <!--ContentPanel - place additional content here--> 
            <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" RenderTransformOrigin="0.5,0.5"
                <Button x:Name="OpenButton" Content="go to OpenState" Click="OpenButton_Click" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
            </Grid> 
             
            <Grid x:Name="GridPopup" Background="DarkBlue" RenderTransformOrigin="0.5,0.5" Grid.RowSpan="2"
                <Grid.RenderTransform> 
                    <CompositeTransform/> 
                </Grid.RenderTransform> 
                <Button x:Name="CloseButton" Content="go to ClosedState" Click="CloseButton_Click" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
            </Grid> 
        </Grid> 

    MainPage.xaml.cs
        public partial class MainPage: PhoneApplicationPage 
        { 
            public MainPage() 
            { 
                InitializeComponent(); 
     
                VisualStateManager.GoToState(this"ClosedState"false); 
            } 
     
            private void CloseButton_Click(object sender, RoutedEventArgs e) 
            { 
                VisualStateManager.GoToState(this"ClosedState"true); 
            } 
     
            private void OpenButton_Click(object sender, RoutedEventArgs e) 
            { 
                VisualStateManager.GoToState(this"OpenState"true); 
            } 
        } 


    Richard Woo

    Tuesday, October 4, 2011 6:13 PM
  • Richard, good post as usual. Answers the questions I had, hopefully for the OP also.

    Tuesday, October 4, 2011 8:05 PM
  • Great post richard, my program seems to be transitioning properly now :)
    Thanks to both of you for lots of help, hopefully I can get this app done without posting any more questions.
    Tuesday, October 4, 2011 10:05 PM