在WPF中实现"向下滑动"动画

And*_*erd 12 wpf animation controltemplate

我正在尝试为Expander控件创建自己的模板.当控件展开时,我希望内容缓慢滑下.

在编译时不知道内容的期望高度.

我以为我们可以将幻灯片定义为动画:

<Storyboard x:Key="ExpandContent">

    <DoubleAnimation 
        Storyboard.TargetName="_expanderContent" 
        Storyboard.TargetProperty="Height" 
        From="0.0" 
        To="{Binding ElementName=_expanderContent,Path=DesiredHeight}"
        Duration="0:0:1.0" />
</Storyboard>
Run Code Online (Sandbox Code Playgroud)

但不幸的是没有.我们收到错误

无法冻结此Storyboard时间轴树以跨线程使用.

看来我们在定义动画参数时不能使用绑定.(也在这个问题中讨论过.)

有没有人对我如何处理这个有任何想法?我担心使用LayoutTransform.ScaleY,因为这会产生扭曲的图像.

这与此问题类似,但这个问题的答案涉及编写代码隐藏,我认为在控件模板中是不可能的.我想知道基于XAML的解决方案是否可以实现.


对于它的价值,这是我的控件模板的当前状态.

<ControlTemplate x:Key="ExpanderControlTemplate"  TargetType="{x:Type Expander}">
    <ControlTemplate.Resources>
            <!-- Here are the storyboards which don't work -->
            <Storyboard x:Key="ExpandContent">

                <DoubleAnimation 
                    Storyboard.TargetName="_expanderContent" 
                    Storyboard.TargetProperty="Height" 
                    From="0.0" 
                    To="{Binding ElementName=_expanderContent,Path=DesiredHeight}"
                    Duration="0:0:1.0" />
            </Storyboard>
            <Storyboard x:Key="ContractContent">

                <DoubleAnimation 
                    Storyboard.TargetName="_expanderContent" 
                    Storyboard.TargetProperty="Height" 
                    From="{Binding ElementName=_expanderContent,Path=DesiredHeight}"
                    To="0.0"
                    Duration="0:0:1.0" />

            </Storyboard>
        </ControlTemplate.Resources>
    <Grid Name="MainGrid" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Name="ContentRow" Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Border>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <ContentPresenter ContentSource="Header" />
                <ToggleButton Template="{StaticResource ProductButtonExpand}"
                              Grid.Column="1"
                              IsChecked="{Binding Path=IsExpanded,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}" 
                              />
                <Rectangle Grid.ColumnSpan="2" Fill="#FFDADADA" Height="1" Margin="8,0,8,2" VerticalAlignment="Bottom"/>

            </Grid>
        </Border>

            <ContentPresenter Grid.Row="1" HorizontalAlignment="Stretch" Name="_expanderContent">

            </ContentPresenter>

    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="IsExpanded" Value="True">
            <Setter TargetName="_expanderContent" Property="Height" Value="{Binding ElementName=_expanderContent,Path=DesiredHeight}" />

                <!-- Here is where I would activate the storyboard if they did work -->
                <Trigger.EnterActions>
                <!--<BeginStoryboard Storyboard="{StaticResource ExpandContent}"/>-->
            </Trigger.EnterActions>
                <Trigger.ExitActions>
                    <!--<BeginStoryboard x:Name="ContractContent_BeginStoryboard" Storyboard="{StaticResource ContractContent}"/>-->
                </Trigger.ExitActions>
        </Trigger>
            <Trigger Property="IsExpanded" Value="False">

                <Setter TargetName="_expanderContent" Property="Height" Value="0" />
            </Trigger>
        </ControlTemplate.Triggers>

</ControlTemplate>
Run Code Online (Sandbox Code Playgroud)

H.B*_*.B. 6

如果你可以用InteractionsFluidLayout(混合4 SDK),你是幸运的,它是为那些花哨的东西动画真正有用的.

首先将内容CP的高度设置为0:

<ContentPresenter Grid.Row="1"
    HorizontalAlignment="Stretch"
    x:Name="_expanderContent"
    Height="0"/>
Run Code Online (Sandbox Code Playgroud)

动画这一点,Height只需要被动画化,以NaNVisualState代表展开状态(非离散动画不会让你使用NaN):

xmlns:is="http://schemas.microsoft.com/expression/2010/interactions"
Run Code Online (Sandbox Code Playgroud)
<Grid x:Name="MainGrid" Background="White">
    <VisualStateManager.CustomVisualStateManager>
        <is:ExtendedVisualStateManager/>
    </VisualStateManager.CustomVisualStateManager>
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="ExpansionStates" is:ExtendedVisualStateManager.UseFluidLayout="True">
            <VisualStateGroup.Transitions>
                <VisualTransition GeneratedDuration="0:0:1"/>
            </VisualStateGroup.Transitions>
            <VisualState x:Name="Expanded">
                <Storyboard>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)"
                                                   Storyboard.TargetName="_expanderContent">
                        <DiscreteDoubleKeyFrame KeyTime="0" Value="NaN"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
            <VisualState x:Name="Collapsed"/>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <!-- ... --->
Run Code Online (Sandbox Code Playgroud)

这应该是所有必要的,流体布局将为您创造过渡.


如果你有一个很好的代码隐藏解决方案,你甚至可以在这样的字典中使用代码隐藏:

<!-- TestDictionary.xaml -->
<ResourceDictionary x:Class="Test.TestDictionary"
                    ...>
Run Code Online (Sandbox Code Playgroud)
//TestDictionary.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;

namespace Test
{
    partial class TestDictionary : ResourceDictionary
    {
        //Handlers and such here
    }
}
Run Code Online (Sandbox Code Playgroud)


Sve*_*son 5

这是一个古老的问题,但是我今天对此有疑问,所以我认为发布我的解决方案是值得的:

我必须为网格行的Height属性设置动画(上下滑动),但需要动态绑定,以便该行可以再次滑动到与以前相同的位置。

我发现此答案非常有帮助(在毫无成效地与XAML对抗之后):http : //go4answers.webhost4life.com/Question/found-solution-work-protected-override-190845.aspx

有时,在后台代码中执行操作会更简单:

        Storyboard sb = new Storyboard();

        var animation = new GridLengthAnimation
        {
                Duration = new Duration(500.Milliseconds()),
                From = this.myGridRow.Height,
                To = new GridLength(IsGridRowVisible ? GridRowPreviousHeight : 0, GridUnitType.Pixel)
        };

        // Set the target of the animation
        Storyboard.SetTarget(animation, this.myGridRow);
        Storyboard.SetTargetProperty(animation, new PropertyPath("Height"));

        // Kick the animation off
        sb.Children.Add(animation);
        sb.Begin();
Run Code Online (Sandbox Code Playgroud)

可以在这里找到GridLengthAnimation类:http : //social.msdn.microsoft.com/forums/en-US/wpf/thread/da47a4b8-4d39-4d6e-a570-7dbe51a842e4/

  • 干得好!比做同一件事所需的所有XAML技巧容易得多。对于所有的MVVM狂热分子来说,这都是“仅UI”代码-克服它。 (2认同)