【发布时间】:2011-10-19 16:59:39
【问题描述】:
我似乎在这里达到了某种 MVVM 断点。
当底层视图模型对象的“状态”属性发生变化时,我希望控件的不透明度动画半秒(DoubleAnimation 从 0.5 到 1.0)。我首先使用 DataTrigger 实现了这一点,但由于我还没有找到一种方法来对任何更改做出反应,只是给定的值,我必须在设置之前将 VM 对象的“状态”属性翻转为特殊的“待定”值达到其预期值。 (有没有办法对任何变化做出反应?)
这很 hacky,所以我开始摆弄 EventTriggers...
这是我迄今为止尝试过的:
- 使用普通的
EventTrigger
这似乎需要一个 RoutedEvent,但这反过来又要求我的底层视图模型对象继承自 DependencyObject。
- 使用
i:Interaction.Triggers
这样我可以收听正常的 .NET 事件并对其做出反应,但我还没有找到使用该方法启动 StoryBoard 的方法。
- 使用
i:Interaction.Triggers并写一个Behavior
我发现无法将我的自定义行为附加到它的关联控件这一事实上,这个实验失败了。
这就是 XAML 的样子:
<cc:MyControl>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Updated">
<i:Interaction.Behaviors>
<cv:OpacityBehavior Duration="0:0:0:5" />
</i:Interaction.Behaviors>
</i:EventTrigger>
</i:Interaction.Triggers>
这是自定义行为:
class OpacityBehavior : Behavior<MyControl>
{
public Duration Duration { get; set; }
protected override void OnAttached()
{
base.OnAttached();
var animation = new DoubleAnimation(0.5, 1, Duration, FillBehavior.HoldEnd);
var associatedObject = lookupVisualParent(this);
associatedObject.BeginAnimation(UIElement.OpacityProperty, animation);
}
}
这不起作用,因为 XAML 解析器要求它直接附加到“MyControl”,但我需要将它附加到事件触发器。然后我尝试了这种方法:
class OpacityBehavior : Behavior<DependencyObject>
{
public Duration Duration { get; set; }
protected override void OnAttached()
{
base.OnAttached();
var animation = new DoubleAnimation(0.5, 1, Duration, FillBehavior.HoldEnd);
var associatedObject = lookupVisualParent(this);
associatedObject.BeginAnimation(UIElement.OpacityProperty, animation);
}
private UIElement lookupVisualParent(DependencyObject dObj)
{
if (dObj is UIElement)
return (UIElement) dObj;
if (dObj == null)
return null;
return lookupVisualParent(LogicalTreeHelper.GetParent(dObj));
}
}
这失败了,因为lookupVisualParent 不起作用。行为的逻辑父级始终为null。
我觉得这应该是一个相当普遍的任务?这个问题有好的解决方案吗?我觉得很奇怪我会编写我的视图模型类,以便它们派生自DependencyObject,以便在事件触发时启动动画。
干杯
【问题讨论】:
标签: wpf events animation eventtrigger