无法使VisualStateGroup.Transitions在模板化控件

时间:2016-11-15 16:44:57

标签: user-controls windows-runtime uwp visualstatemanager

我正在创建一个模板控件。我们的想法是创建一个扩展控件。它将具有Header和Details属性,每个属性对应ContentPresenter。用户将能够点击标题,详细信息部分将以动画展开。当用户再次点击标题时,“详细信息”部分将使用另一个动画缩回。

我正在使用Visual States和VisualTransitions来实现这一目标。这是我的代码。

[TemplatePart(Name ="Header", Type=typeof(ContentPresenter))]
[TemplatePart(Name = "Details", Type = typeof(ContentPresenter))]
[TemplateVisualState(GroupName ="ExpandStates",Name ="Expanded")]
[TemplateVisualState(GroupName = "ExpandStates", Name = "Compact")]
public sealed class ExpandingItem : Control
{

    private ContentPresenter header;
    private bool isExpanded;

    public ExpandingItem()
    {
        this.DefaultStyleKey = typeof(ExpandingItem);
    }

    public FrameworkElement Header
    {
        get { return (FrameworkElement)GetValue(HeaderProperty); }
        set { SetValue(HeaderProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Header.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty HeaderProperty =
        DependencyProperty.Register("Header", typeof(FrameworkElement), typeof(ExpandingItem), new PropertyMetadata(default(FrameworkElement)));


    public FrameworkElement Details
    {
        get { return (FrameworkElement)GetValue(DetailsProperty); }
        set { SetValue(DetailsProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Details.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty DetailsProperty =
        DependencyProperty.Register("Details", typeof(FrameworkElement), typeof(ExpandingItem), new PropertyMetadata(default(FrameworkElement)));



    protected override void OnApplyTemplate()
    {
        if (header != null)
        {
            header.Tapped -= HeaderTapped;
        }

        base.OnApplyTemplate();

        header = (ContentPresenter)GetTemplateChild("Header");
        header.Tapped += HeaderTapped;
    }

    private void HeaderTapped(object sender, TappedRoutedEventArgs e)
    {
        if (isExpanded)
        {
            Retract();
            OnStateChanged(new ExpandItemEventArgs(false));
        }
        else
        {
            Expand();
            OnStateChanged(new ExpandItemEventArgs(true));
        }
        isExpanded = !isExpanded;
    }


    public void Expand()
    {
        VisualStateManager.GoToState(this, "Expanded", true);
    }

    public void Retract()
    {
        VisualStateManager.GoToState(this, "Compact", true);
    }

    public EventHandler<ExpandItemEventArgs> StateChanged;
    private void OnStateChanged(ExpandItemEventArgs e)
    {
        // Make a temporary copy of the event to avoid possibility of
        // a race condition if the last subscriber unsubscribes
        // immediately after the null check and before the event is raised.
        EventHandler<ExpandItemEventArgs> handler = StateChanged;

        // Event will be null if there are no subscribers
        if (handler != null)
        {
            handler(this, e);
        }
    }
}

和模板

<Style TargetType="controls:ExpandingItem" >
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="controls:ExpandingItem">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="ExpandStates">
                            <VisualStateGroup.Transitions>
                                <VisualTransition From="Compact" To="Expanded">
                                    <VisualTransition.Storyboard>
                                        <Storyboard>
                                            <FadeInThemeAnimation
                                                TargetName="Details"/>
                                        </Storyboard>
                                    </VisualTransition.Storyboard>
                                </VisualTransition>
                                <VisualTransition From="Expanded" To="Compact">
                                    <VisualTransition.Storyboard>
                                        <Storyboard>
                                            <FadeOutThemeAnimation
                                                TargetName="Details"/>
                                        </Storyboard>
                                    </VisualTransition.Storyboard>
                                </VisualTransition>
                            </VisualStateGroup.Transitions>
                            <VisualState x:Name="Compact"/>

                            <VisualState x:Name="Expanded">
                                <VisualState.Setters>
                                    <Setter Target="Details.Visibility" Value="Visible"/>
                                </VisualState.Setters>
                                <Storyboard>
                                    <FadeInThemeAnimation
                                                TargetName="Details"/>
                                </Storyboard>
                            </VisualState>

                        </VisualStateGroup>                        
                    </VisualStateManager.VisualStateGroups>


                    <ContentPresenter
                        x:Name="Header"
                        Grid.Row="0"
                        Content="{TemplateBinding Header}"/>

                    <ContentPresenter
                        x:Name="Details"
                        Grid.Row="1"
                        Content="{TemplateBinding Details}"
                        Visibility="Collapsed"/>

                </Grid>

            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我正在使用fadein / fadeout动画,因为它是一个简单的动画,但理想情况下我想使用像splitopen / splitclose动画这样的东西。

问题在于即使状态之间的转换正常发生。动画永远不会发生。你能帮我找出问题吗?

编辑:以下是ExpandItemEventArgs

的代码
 public class ExpandItemEventArgs : EventArgs
{
    private readonly bool isExpanded;

    public ExpandItemEventArgs(bool isExpanded)
    {
        this.isExpanded = isExpanded;
    }

    public bool IsExpanded => isExpanded;
}

1 个答案:

答案 0 :(得分:0)

  

问题在于即使状态之间的转换正常发生。动画永远不会发生。你能帮我找出问题吗?

这是因为您的VisualTransition From="Compact" To="Expanded",首先您没有让您的控件进入名为VisualState的{​​{1}}。当你Compact时,由于你没有为<VisualTransition From="Expanded" To="Compact">设置Visibility属性,它会删除最后Details并直接返回到折叠状态,动画将不会显示。

在这里我修改了你的代码,为了使淡入淡出的动画更明显,我也改变了动画:

VisualState

我修改后面的代码:

<Style TargetType="local:ExpandingItem">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:ExpandingItem">
                <Grid Name="RootGrid">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="ExpandStates">
                            <VisualStateGroup.Transitions>
                                <VisualTransition To="Expanded" GeneratedDuration="0:0:3">
                                    <Storyboard x:Name="FadeIn">
                                        <DoubleAnimation From="0.1" To="1" Storyboard.TargetProperty="Opacity"
                                            Storyboard.TargetName="Details" Duration="0:0:3">
                                            <DoubleAnimation.EasingFunction>
                                                <CubicEase />
                                            </DoubleAnimation.EasingFunction>
                                        </DoubleAnimation>
                                    </Storyboard>
                                </VisualTransition>
                                <VisualTransition From="Expanded" To="Compact" GeneratedDuration="0:0:2.5">
                                    <VisualTransition.Storyboard>
                                        <Storyboard x:Name="FadeOut">
                                            <DoubleAnimation From="1" To="0.1" Storyboard.TargetProperty="Opacity"
                                                Storyboard.TargetName="Details" Duration="0:0:3">
                                                <DoubleAnimation.EasingFunction>
                                                    <CubicEase />
                                                </DoubleAnimation.EasingFunction>
                                            </DoubleAnimation>
                                        </Storyboard>
                                    </VisualTransition.Storyboard>
                                </VisualTransition>
                            </VisualStateGroup.Transitions>

                            <VisualState x:Name="Normal">
                                <VisualState.Setters>
                                    <Setter Target="Details.Visibility" Value="Visible" />
                                </VisualState.Setters>
                            </VisualState>

                            <VisualState x:Name="Compact">
                                <VisualState.Setters>
                                    <Setter Target="Details.Visibility" Value="Collapsed" />
                                </VisualState.Setters>
                            </VisualState>

                            <VisualState x:Name="Expanded">
                                <VisualState.Setters>
                                    <Setter Target="Details.Visibility" Value="Visible" />
                                </VisualState.Setters>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>

                    <ContentPresenter
                    x:Name="Header"
                    Grid.Row="0"
                    Content="{TemplateBinding Header}" />

                    <ContentPresenter
                    x:Name="Details"
                    Grid.Row="1"
                    Content="{TemplateBinding Details}" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

渲染图片:

enter image description here