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>
This question is more complex than I initially thought.
First, let's correct a few issues in your xaml code.
- The following line needs to be removed. It's like saying 'go find a state named
OverlayStateon thecheckedBorderelement'. Clearly that state is not on that element. Also, changing theElementNamebinding to point to the top levelGrid(where the visual state group is) won't work either, I will explain why later.
TargetObject="{Binding ElementName=checkedBorder}"
- You should always give your
VisualStateGroupa name, like this -
<VisualStateGroup x:Name="MyStates">
- You need to set
IsHitTestVisibletoFalseon your overlayBorder, otherwise theBorderwith image background will not be able to receive theTappedevent 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