Goto VisualState in Listivew item DateTemplate windows phone 8.1

百般思念 提交于 2019-12-10 11:15:22

问题


My requirement: when tapped on the border in ListViewItem(DataTemplate) an overlay should appear on top of it with animation.

In my listview data template I defined a visual state at the root. I want to goto the visual state when user taps on the border. I have tried following xaml but it is not working

<DataTemplate x:Key="MyTemplate">
        <Grid Background="{Binding ItemBackground}"
          Margin="0,0,0,5" Height="auto">
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup >
                    <VisualState x:Name="OverlayState">
                        <Storyboard >
                            <DoubleAnimation Storyboard.TargetName="checkedBorder"
                                                 Storyboard.TargetProperty="Opacity"
                                                 Duration="0"
                                                 To="1" />
                        </Storyboard>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>

            <Grid Height="auto" Margin="14,0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="110"></ColumnDefinition>
                    <ColumnDefinition Width="*"></ColumnDefinition>
                    <ColumnDefinition Width="55"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto"></RowDefinition>
                    <RowDefinition Height="auto"></RowDefinition>
                </Grid.RowDefinitions>

                <!--Image Section" -->
                <Grid Height="108" Margin="0,8,0,0" VerticalAlignment="Top">
                    <Grid Margin="0">
                        <Border HorizontalAlignment="Left" Margin="0" VerticalAlignment="Bottom" Width="98" Height="98" CacheMode="BitmapCache" CornerRadius="30">
                            <Border.Background>
                                <ImageBrush ImageSource="{Binding ImageSource}"  Stretch="Fill"></ImageBrush>
                            </Border.Background>
                            <i:Interaction.Behaviors>
                                <icore:EventTriggerBehavior EventName="Tapped">
                                    <icore:GoToStateAction StateName="OverlayState" TargetObject="{Binding ElementName=checkedBorder}"></icore:GoToStateAction>
                                </icore:EventTriggerBehavior>
                            </i:Interaction.Behaviors>
                        </Border>

                        <!-- Overlay Border -->
                        <Border HorizontalAlignment="Left" Opacity="0" x:Name="checkedBorder" Margin="0" Background="#99000000" VerticalAlignment="Bottom"                                 
                            Width="98" Height="98" CacheMode="BitmapCache" CornerRadius="30">
                        </Border>
                    </Grid>
                </Grid>
            </Grid>
        </Grid>
    </DataTemplate>

回答1:


This question is more complex than I initially thought.

First, let's correct a few issues in your xaml code.

  1. The following line needs to be removed. It's like saying 'go find a state named OverlayState on the checkedBorder element'. Clearly that state is not on that element. Also, changing the ElementName binding to point to the top level Grid (where the visual state group is) won't work either, I will explain why later.

TargetObject="{Binding ElementName=checkedBorder}"

  1. You should always give your VisualStateGroup a name, like this -

<VisualStateGroup x:Name="MyStates">

  1. You need to set IsHitTestVisible to False on your overlay Border, otherwise the Border with image background will not be able to receive the Tapped event because it's sitting behind the overlay one.

I thought it should be good to go. However, if you run the app now, you will get an unhandled exception saying

Target does not define any VisualStateGroups.

If you add back the TargetObject ElementName binding and change it to point to the top level Grid, the exception will go away but the visual state is not called.

TargetObject="{Binding ElementName=myFirstLevelGridWhereTheVSGroupIs}"

This is because a normal VisualStateManager only works for Controls not FrameworkElements since your Grid is not a type of Control.

In a WP Silverlight app, it's fairly simple to fix. All you need to do is to add a built-in CustomVisualStateManager which allows you to pass in a FrameworkElement on top of the VisualStateGroups definition. But such class doesn't exist in WinRT.

I asked a question about this a while ago and eventually came up with an answer.

Include this class into your project, and add the reference in your xaml code, just before your VisualStateGroups definition.

<VisualStateManager.CustomVisualStateManager>
    <local:ExtendedVisualStateManager />
</VisualStateManager.CustomVisualStateManager>

<VisualStateManager.VisualStateGroups>
    <VisualStateGroup x:Name="MyStates">
        <VisualState x:Name="OverlayState">

Lastly, because unlike the GoToStateAction in Silverlight app, the WinRT's GoToStateAction doesn't handle CustomVisualStateManager, you will have to create a custom GoToStateAction too.

public class ExtendedGoToStateAction : DependencyObject, IAction
{
    public string StateName
    {
        get { return (string)GetValue(StateNameProperty); }
        set { SetValue(StateNameProperty, value); }
    }

    public static readonly DependencyProperty StateNameProperty =
        DependencyProperty.Register("StateName", typeof(string), typeof(ExtendedGoToStateAction), new PropertyMetadata(string.Empty));

    public bool UseTransitions
    {
        get { return (bool)GetValue(UseTransitionsProperty); }
        set { SetValue(UseTransitionsProperty, value); }
    }

    public static readonly DependencyProperty UseTransitionsProperty =
        DependencyProperty.Register("UseTransitions", typeof(bool), typeof(ExtendedGoToStateAction), new PropertyMetadata(false));     

    public object Execute(object sender, object parameter)
    {
        return ExtendedVisualStateManager.GoToElementState((FrameworkElement)sender, this.StateName, this.UseTransitions);
    }
}

And replace the built-in one with this.

<i:Interaction.Behaviors>
    <iCore:EventTriggerBehavior EventName="Tapped">
        <local:ExtendedGoToStateAction StateName="OverlayState"/>
    </Core:EventTriggerBehavior>

You should be able to see the animation working now. :)



来源:https://stackoverflow.com/questions/27899755/goto-visualstate-in-listivew-item-datetemplate-windows-phone-8-1

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!