【发布时间】:2011-09-27 02:53:57
【问题描述】:
我在我的应用程序中使用了类似于扩展器的分组框。当我需要折叠一个组合框时,我将其高度设置为 0。当我需要展开它时,我将其高度设置为 auto (double.Nan) 是否可以使用情节提要执行此操作。我怎么能提前知道自动高度。表达式混合无法让我制作自动动画。
【问题讨论】:
标签: c# wpf xaml animation storyboard
我在我的应用程序中使用了类似于扩展器的分组框。当我需要折叠一个组合框时,我将其高度设置为 0。当我需要展开它时,我将其高度设置为 auto (double.Nan) 是否可以使用情节提要执行此操作。我怎么能提前知道自动高度。表达式混合无法让我制作自动动画。
【问题讨论】:
标签: c# wpf xaml animation storyboard
我讨厌比例变换,因为我觉得它很丑,所以我寻找了另一种解决方案。
好吧,我知道这是一篇旧帖子,并且存在许多解决方法,但我的很简单,即使有人确定找到它,我也没有在其他地方阅读过它。
不是将高度从 X 设置为 Auto(这是不可能的),您可以让高度设置为 Auto 并为 MaxHeight 属性设置动画:
<MyControl x:Name="ctrlAutoHeight" Height="Auto">
<MyControl.Triggers>
<EventTrigger RoutedEvent="myRoutedEvent">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="ctrlAutoHeight"
Storyboard.TargetProperty="MaxHeight"
From="0.0"
To="{Binding ElementName=ParentControl, Path=ActualHeight}"
Duration="0:0:1"
AutoReverse="False"
/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</MyControl.Triggers>
</MyControl>
【讨论】:
To 绑定到我的窗口的 MaxHeight 或它的网格时,我得到了一个 InvalidOperationException。
您可以为此使用 ScaleTransform
<GroupBox Header="GroupBox">
<GroupBox.RenderTransform>
<ScaleTransform ScaleY="1"/>
</GroupBox.RenderTransform>
</GroupBox>
当折叠一个组合框时将 ScaleTransform.ScaleX 设置为 0。当展开时设置为 1。
【讨论】:
这是一个基于 StackPanel 的即用型示例(请随意将其替换为 GroupBox)。
对于那些具有 «InvalidOperationException: 无法冻结此 Storyboard 时间线树以供跨线程使用。» 的情况,此异常发生在 Storyboard 中定义绑定时,该绑定本身定义在 ControlTemplate 或 Style 中。 在某种程度上,冻结动画是一种所有值都是静态的动画(假设是预先计算的)。
只是为了感觉问题,想象一下 StackPanel 在动画过程中被添加或删除了一些控件,理论上要成功实现这个动画,动画引擎应该考虑到这些变化(通过绑定), 但不幸的是,WPF 实际上并不支持这种情况。
要回到下面的解决方案,请注意我正在使用任何 ControlTemplate 或 Style 之外的绑定。 在这种情况下,动画参数是在触发事件时计算的,但一旦播放,它们不会在绑定属性更改时更新。
因此,此解决方案(除非其他解决方案)存在 2 个非阻塞问题:
<StackPanel>
<!-- CheckBox used for triggering the StackPanel animation -->
<CheckBox Content="Expand/Collapse">
<CheckBox.Triggers>
<EventTrigger RoutedEvent="CheckBox.Checked">
<!-- Expand animation -->
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="StackPanel"
Storyboard.TargetProperty="Height"
From="{Binding ElementName=StackPanel, Path=Height}"
To="{Binding ElementName=ContentSize, Path=DesiredSize.Height}"
Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="CheckBox.Unchecked">
<!-- Collapse animation -->
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="StackPanel"
Storyboard.TargetProperty="Height"
From="{Binding ElementName=StackPanel, Path=Height}"
To="0"
Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</CheckBox.Triggers>
</CheckBox>
<!-- The animated StackPanel -->
<StackPanel x:Name="StackPanel" Height="0">
<!-- The border below acts as a probe to get the expected StackPanel container size -->
<Border x:Name="ContentSize">
<TextBlock>Some Content</TextBlock>
</Border>
</StackPanel>
</StackPanel>
到目前为止,似乎还没有完美而简单的解决方案来解决这个问题......
【讨论】: