Search code examples
silverlightwindows-phone-7expression-blend

story board states, transition and visibility property


I am playing for the first time with Expression Blend. I made a very simple overlay grid that occupies all the screen space.

<!-- phone application page -->
<Grid x:Name="LayoutRoot">
    <Grid>
      <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
       </Grid.RowDefinitions>
    </Grid>
    <TextBlock Grid.Row="0" Text="Some Content" />
    <TextBlock Grid.Row="1" Text="Some Other Content />
    <Grid x:Name="Overlay" Grid.RowSpan="2" Background="Black" Opacity="0" Visibility="Collapsed">
       <TextBlock Text="Loading..." />
       <toolkit:PerformanceProgressBar x:Name="ProgressBar" IsIndeterminate="False" />
    </Grid>       
</Grid>

I want the overlay grid to have 2 states:

  • LoadingState
  • NotLoadingState

where LoadingState:

  • ProgressBar.IsIndeterminate="True"
  • Opacity="80"
  • Visibility="Visible"

NotLoadingState (basically what it is set as default in xaml):

  • ProgressBar.IsIndeterminate="False"
  • Opacity="0"
  • Visibility="Collapsed"

The time between transitions: 0.5s

I am triggering the states in code-behind like this:

   private void VmPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (e.PropertyName == ListViewModel.IsLoadingPropertyName)
        {
            if (_vm.IsLoading)
            {
                VisualStateManager.GoToState(this, LoadingStatePropertyName, true);
            }
            else
            {
                VisualStateManager.GoToState(this, NotLoadingStatePropertyName, true);
            }
        }
    }

Yet as simple as the code above looks I couldn't get the transitions to work. Changing the state to LoadingState works, and I get a nice Opacity animation, but it doesn't the other way around (LoadingState -> NotLoadingState) - the Overlay Grid just disappears without any animation. I am guessing that's because the Visibility gets set to Collapsed. I've been trying to come up with something in Expression Blend but nothing worked so far.

Here's th requested generated source:

<VisualStateManager.VisualStateGroups>
    <VisualStateGroup x:Name="LoadingStateGroup">
        <VisualStateGroup.Transitions>
            <VisualTransition From="LoadingState" GeneratedDuration="0" To="NotLoadingState">
                <Storyboard>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="Overlay">
                        <EasingDoubleKeyFrame KeyTime="0" Value="0.8"/>
                        <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
                    </DoubleAnimationUsingKeyFrames>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Overlay">
                        <DiscreteObjectKeyFrame KeyTime="0">
                            <DiscreteObjectKeyFrame.Value>
                                <Visibility>Visible</Visibility>
                            </DiscreteObjectKeyFrame.Value>
                        </DiscreteObjectKeyFrame>
                        <DiscreteObjectKeyFrame KeyTime="0:0:0.5">
                            <DiscreteObjectKeyFrame.Value>
                                <Visibility>Collapsed</Visibility>
                            </DiscreteObjectKeyFrame.Value>
                        </DiscreteObjectKeyFrame>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </VisualTransition>
            <VisualTransition From="NotLoadingState" GeneratedDuration="0" To="LoadingState">
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Overlay">
                        <DiscreteObjectKeyFrame KeyTime="0">
                            <DiscreteObjectKeyFrame.Value>
                                <Visibility>Visible</Visibility>
                            </DiscreteObjectKeyFrame.Value>
                        </DiscreteObjectKeyFrame>
                        <DiscreteObjectKeyFrame KeyTime="0:0:0.5">
                            <DiscreteObjectKeyFrame.Value>
                                <Visibility>Visible</Visibility>
                            </DiscreteObjectKeyFrame.Value>
                        </DiscreteObjectKeyFrame>
                    </ObjectAnimationUsingKeyFrames>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="Overlay">
                        <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                        <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0.795"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </VisualTransition>
            <VisualTransition GeneratedDuration="0"/>
        </VisualStateGroup.Transitions>
        <VisualState x:Name="LoadingState">
            <Storyboard>
                <DoubleAnimation Duration="0" To="0.795" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="Overlay" d:IsOptimized="True"/>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Overlay">
                    <DiscreteObjectKeyFrame KeyTime="0">
                        <DiscreteObjectKeyFrame.Value>
                            <Visibility>Visible</Visibility>
                        </DiscreteObjectKeyFrame.Value>
                    </DiscreteObjectKeyFrame>
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </VisualState>
        <VisualState x:Name="NotLoadingState">
            <Storyboard>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Overlay">
                    <DiscreteObjectKeyFrame KeyTime="0">
                        <DiscreteObjectKeyFrame.Value>
                            <Visibility>Collapsed</Visibility>
                        </DiscreteObjectKeyFrame.Value>
                    </DiscreteObjectKeyFrame>
                </ObjectAnimationUsingKeyFrames>
                <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="Overlay" d:IsOptimized="True"/>
            </Storyboard>
        </VisualState>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

Solution

  • What you need is Fluid Layout. It's specifically designed to solve this problem. You can read more here (good read, if a bit long) and the corresponding samples are here. There's even a Windows Phone 7 specific tutorial over here.