WPF动画“无法冻结此故事板时间线树以在跨线程中使用”

29

我目前有一个列表框,它的选择项绑定到我的ViewModel中的某个属性。每当选择项不为空时,我希望对其执行动画。但是,我一直收到"Cannot freeze this Storyboard timeline tree for use across threads"的错误提示,并从研究中了解到了发生这种情况的原因。但我不确定需要采取什么方法才能获得我想要的行为。

<Storyboard x:Key="ShowItemEdit">
    <DoubleAnimation
        Storyboard.TargetName="lstItemList"
        Storyboard.TargetProperty="ListBox.Width"
        To="{Binding ActualWidth, ElementName=UserControl}"
        Duration="0:0:0.40" />
    ...
</Storyboard>

<Style x:Key="ListStyle">
    <Style.Triggers>
        <DataTrigger Binding="{Binding SelectedItem, Converter={StaticResource IsNullConverter}}" Value="False">
            <DataTrigger.EnterActions>
            <BeginStoryboard Storyboard="{StaticResource ShowItemEdit}" />
        </DataTrigger.EnterActions>
        </DataTrigger>
     </Style.Triggers>
</Style>

<ListBox x:Name="lstItemList" Style={StaticResource ListStyle}" SelectedItem="{Binding SelectedItem}">
    ...
</ListBox>
3个回答

45

你可以发布你的Storyboard吗?听起来你在Storyboard定义中使用了某种绑定。


好的,正如我所怀疑的那样,这是因为您在Storyboard中使用了一个Binding。您不能这样做,因为WPF尝试冻结模板使用的所有资源以提高效率,当您在Freezable上使用绑定时,即在此情况下的Storyboard,它会防止其被冻结。


我添加了故事板代码。我绑定'To'属性,因为我不想硬编码宽度。 - jwarzech
1
那么这就是你的问题了,我来解释一下。 - Drew Marsh
谢谢您的解释!您有什么建议,我如何在不连接数据触发器到控件的情况下实现这个带绑定的故事板呢? - jwarzech
根据我的猜测,您想要通过动画实现什么样的效果?如果您将ListBox的宽度设置为HorizontalAlignment.Stretch,并给它一个Margin,然后将此Storyboard动画化为Margin到0,而不是将宽度设置为UserControl的ActualWidth,这样会更好。 - Drew Marsh
3
谢谢提示!这不是由于绑定,而是使用Dynamicresources发生了。 - dba
3
我也遇到了DynamicResources的问题。在这种情况下,我该如何使用动态资源?我需要引用一个存储在资源字典中的颜色。 - Ben Hayward

11

有一种技巧可以解决 Freezable 问题,允许您在动画的 "To" 值上使用绑定(而不是在那里硬编码一个值)。这很简单,我已经在这里概述了它。


感谢您发布这篇文章。然而,由于此技术使用了标签属性,必须补充说明它只能用于动画化一个属性,比如 OP 示例中的宽度。如果您计划将此方法用于宽度和高度,以进行更复杂的动画,则不起作用,除非您要动画化一个正方形。 - Alexandru Dicu

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接