Goto VisualState in Listivew item DateTemplate windows phone



我的要求:在ListViewItem(DataTemplate)中点击边框时,应该在其顶部出现一个带有动画的叠加层。

在我的列表视图数据模板中,我在根目录定义了视觉状态。我想在用户点击边框时进入视觉状态。我试过遵循 xaml,但它不起作用

<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>

这个问题比我最初想象的要复杂。

首先,让我们更正 xaml 代码中的一些问题。

  1. 需要删除以下行。这就像说"在checkedBorder元素上找到一个名为OverlayState的状态"。显然,该状态不在该元素上。此外,将ElementName绑定更改为指向顶级Grid(视觉状态组所在的位置)也不起作用,稍后我将解释原因。

TargetObject="{Binding ElementName=checkedBorder}"

  1. 你应该总是给你的VisualStateGroup起一个名字,就像这样——

<VisualStateGroup x:Name="MyStates">

  1. 您需要将IsHitTestVisible设置为在叠加BorderFalse,否则具有图像背景的Border将无法接收Tapped事件,因为它位于叠加事件后面。

我想应该很好。但是,如果您现在运行该应用程序,您将收到一个未处理的异常,指出

Target 未定义任何 VisualStateGroups。

如果重新添加TargetObject ElementName绑定并将其更改为指向顶级Grid,则异常将消失,但不调用视觉状态。

TargetObject="{Binding ElementName=myFirstLevelGridWhereTheVSGroupIs}"

这是因为正常的VisualStateManager仅适用于Control而不是FrameworkElement,因为您的Grid不是一种Control

在WP Silverlight应用程序中,修复起来相当简单。您需要做的就是添加一个内置CustomVisualStateManager,它允许您在VisualStateGroups定义之上传入FrameworkElement。但此类在 WinRT 中不存在。

不久前我问了一个关于这个问题的问题,最终得出了答案。

将此类包含在项目中,并在 xaml 代码中添加引用,紧接在VisualStateGroups定义之前。

<VisualStateManager.CustomVisualStateManager>
    <local:ExtendedVisualStateManager />
</VisualStateManager.CustomVisualStateManager>
<VisualStateManager.VisualStateGroups>
    <VisualStateGroup x:Name="MyStates">
        <VisualState x:Name="OverlayState">

最后,由于与 Silverlight 应用程序中的GoToStateAction不同,WinRT 的GoToStateAction不处理CustomVisualStateManager ,您还必须创建自定义GoToStateAction

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);
    }
}

并用这个替换内置的。

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

您应该能够看到动画现在正在工作。 :)

最新更新