简体   繁体   中英

WP7 VisualState change programmatically

I'm trying to create an Image, that when it's touched, a small popup appears. When you touch it again (or anywhere outside) it should dissapear.
I've created the popup, and some visual state transitions to hide and collapse

<Grid x:Name="LayoutRoot" Background="Transparent">
    <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="PopupVisibility">
                    <VisualState x:Name="PopupVisible">
                        <Storyboard>
                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="PopupControl">
                                <DiscreteObjectKeyFrame KeyTime="0">
                                    <DiscreteObjectKeyFrame.Value>
                                        <Visibility>Visible</Visibility>
                                    </DiscreteObjectKeyFrame.Value>
                                </DiscreteObjectKeyFrame>
                            </ObjectAnimationUsingKeyFrames>
                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="PopupControl">
                                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                                <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
                            </DoubleAnimationUsingKeyFrames>
                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="PopupControl">
                                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                                <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
                            </DoubleAnimationUsingKeyFrames>
                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)" Storyboard.TargetName="PopupControl">
                                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                                <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                    </VisualState>
                    <VisualState x:Name="PopupCollapsed">
                        <Storyboard>
                            <DoubleAnimation Duration="0:0:0.5" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="PopupControl" d:IsOptimized="True"/>
                            <DoubleAnimation Duration="0:0:0.5" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)" Storyboard.TargetName="PopupControl" d:IsOptimized="True"/>
                            <DoubleAnimation Duration="0:0:0.5" To="0" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="PopupControl" d:IsOptimized="True"/>
                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="PopupControl">
                                <DiscreteObjectKeyFrame KeyTime="0:0:0.5">
                                    <DiscreteObjectKeyFrame.Value>
                                        <Visibility>Visible</Visibility>
                                    </DiscreteObjectKeyFrame.Value>
                                </DiscreteObjectKeyFrame>
                                <DiscreteObjectKeyFrame KeyTime="0:0:0.7">
                                    <DiscreteObjectKeyFrame.Value>
                                        <Visibility>Collapsed</Visibility>
                                    </DiscreteObjectKeyFrame.Value>
                                </DiscreteObjectKeyFrame>
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>

<Button Content="Text" HorizontalAlignment="Right" Margin="0,0,12,-37" Width="152" Background="#00C06B6B" Height="75" VerticalAlignment="Bottom" Visibility="Visible">
            <Custom:Interaction.Triggers>
                <Custom:EventTrigger EventName="Click">
                    <ic:GoToStateAction x:Name="GoToStatePopupVisible" StateName="PopupVisible"/>
                </Custom:EventTrigger>
                <Custom:EventTrigger EventName="LostFocus">
                    <ic:GoToStateAction x:Name="LostFocus" StateName="PopupCollapsed"/>
                </Custom:EventTrigger>
            </Custom:Interaction.Triggers>
        </Button>

 <Grid x:Name="PopupControl" Height="241" Margin="39,-28,203,0" Grid.Row="1" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.5">





                <Grid.RenderTransform>
                <CompositeTransform/>
            </Grid.RenderTransform>
            <Rectangle Stroke="Black">
                <Rectangle.Fill>
                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                        <GradientStop Color="#FF726969" Offset="1"/>
                        <GradientStop Color="White"/>
                    </LinearGradientBrush>
                </Rectangle.Fill>
            </Rectangle>
            <TextBlock TextWrapping="Wrap" Text="TextBlock" d:LayoutOverrides="Width" Foreground="#FF1D0E0E" Margin="5"/>
        </Grid>
<Image HorizontalAlignment="Right" Height="100" Margin="0,-38,37,0" Grid.Row="1" VerticalAlignment="Top" Width="100" Source="Images/pushpin.jpg" ManipulationStarted="Image_ManipulationStarted">
        </Image>

</Grid>

I tried using Blend to test this, and works fine, for example, adding a button and creating an eventtrigger:

<Button Content="Text" HorizontalAlignment="Right" Margin="0,0,12,-37" Width="152" Background="#00C06B6B" Height="75" VerticalAlignment="Bottom" Visibility="Visible">
            <Custom:Interaction.Triggers>
                <Custom:EventTrigger EventName="Click">
                    <ic:GoToStateAction x:Name="GoToStatePopupVisible" StateName="PopupVisible"/>
                </Custom:EventTrigger>
                <Custom:EventTrigger EventName="LostFocus">
                    <ic:GoToStateAction x:Name="LostFocus" StateName="PopupCollapsed"/>
                </Custom:EventTrigger>
            </Custom:Interaction.Triggers>
        </Button>

However, when trying the "real" thing, I need more logic than this. If I press the image and it's visible, i want it to transition to collapsed, and viceversa. So I save my current visibility state

(VisualStateManager.GetVisualStateGroups(LayoutRoot)[0] as VisualStateGroup).CurrentStateChanged += new EventHandler<VisualStateChangedEventArgs>(MainPage_CurrentStateChanged);

public string CurrentState { get; set; }

        void MainPage_CurrentStateChanged(object sender, VisualStateChangedEventArgs e)
        {
            CurrentState = e.NewState.Name;
        }

And then i create the image:

<Image HorizontalAlignment="Right" Height="100" Margin="0,-38,37,0" Grid.Row="1" VerticalAlignment="Top" Width="100" Source="Images/pushpin.jpg" ManipulationStarted="Image_ManipulationStarted">
            </Image>

Finally, I programmatically try to do the same thing than the eventtrigger does, but with some logic:

private void Image_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
        {
            switch (CurrentState)
            {
                case "PopupVisible":
                    {
                        ExtendedVisualStateManager.GoToElementState(LayoutRoot, "PopupCollapsed", true);
                        break;
                    }
                case "PopupCollapsed":
                    {
                        ExtendedVisualStateManager.GoToElementState(LayoutRoot, "PopupVisible", true);
                        break;
                    }
            }
        }

I tried both VisualStateManager and ExtendedVisualStateManager methods GoToState and GoToElementState, but to no avail. The methods always return false and nothing changes on the screen. What am i doing wrong??

I presume that you debugged the code so you know that the control gets to ManipulationSTarted handler.

Acc. to msdn VisualStateManager.GoToState documentation: " If stateName doesn't exist in the ControlTemplate of control, GoToState takes no action and returns false. "

From the above code I am not able to judge what's the LayoutRoot and whether the states are really defined at that element. (A side remark: Popup does some manipulation of the visual tree, which in some cases could explain above behavior.)

On the other hand, I don't understand why you use Xaml in this case. In my opinion you can do it much easier in the code. (Not to speak about the performance.):

  1. Create 2 storyboards in the code

  2. Run them as needed from ManipulationStarted handler.

If you don't know how to work with Storyboards in the code, look for example at this my article .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM