如何为WPF WebBrowser制作动画

时间:2012-07-12 04:35:49

标签: wpf .net-3.5 browser storyboard

将此记录为一个问题和答案,以便其他人不必遭受同样的痛苦。

我有一个动画页面的WPF应用程序,就像在iPhone上滑动一样。在包含WebBrowser所需的页面之前,一切都很好。它对动画没有任何反应 - 当它应该滑入时,直到你聚焦它才会出现,当它应该滑出时,它会消失,直到你将鼠标移到它上面。在这两种情况下,它只是弹出/放出而不是动画。

使问题复杂化,在项目期间,由于无关原因,决定回到.net 3.5而不是4。

所以问题是:我怎样才能(a)让WebBrowser正确地制作动画;或(b)如何在动画开始时隐藏WebBrowser并在结束时再次显示它。动画当前在XAML中定义,我不特别想将其更改为代码。

后续问题是:还有更好的方法,还在使用.net 3.5吗?

1 个答案:

答案 0 :(得分:2)

更新 与WinForms相比,WPF WebBrowser非常可怜,我使用WindowsFormsHost进行了交换。下面的所有内容仍然适用,但WebBrowser现在并没有如此拙劣(例如,它有一个DocumentCompleted事件)。


我很快就放弃了为WebBrowser制作动画的选项,因为它太过刻苦了,而是决定隐藏并重新展示它。动画的开始由视图模型上的命令触发。然后它会找到应该显示的页面,创建它,并通过反映过渡状态的附加属性启动动画。

我创建了一个界面IRequireTransitionInfo,以便调用IRequireTransitionInfo.TransitioningFrom使其有机会隐藏自己并IRequireTransitionInfo.TransitioningTo再次显示。 TransitioningFrom很简单,但在故事板完成时必须调用TransitioningTo。

最初,在View Model的构造函数中,它继续寻找Storyboard并挂钩其Completed事件,如下面的代码所示:

    Storyboard animation = Application.Current.FindResource("SlideAnimation") as Storyboard;
    if (animation != null)
    {
      animation.Completed += new EventHandler(animation_Completed);
    }

然后是事件处理程序:

void animation_Completed(object sender, EventArgs e)
{
  IRequireTransitionInfo info = currentViewModel as IRequireTransitionInfo;
  if (info != null)
    info.TransitioningTo(currentView);
}

这似乎与.net 4相当不错。在降级到.net 3.5后,当上面的代码连接完成事件时,我收到了以下错误:

Specified value of type 'System.Windows.Media.Animation.Storyboard' must have IsFrozen set to false to modify.

尽管SO上有其他一些答案,但是你无法解冻冻结的Freezable,并且将代码移动到MainWindow的构造函数中也无济于事。

我沿着视图模型上的命令绑定了故事板上附加属性的路径。

<Storyboard x:Key="SlideAnimation" local:EventCommand.StoryboardCompleted="{Binding Source={StaticResource Locator}, Path=Current.MainViewModel.StoryboardCompletedCommand}">

但是,这会在运行时导致以下错误:

Cannot convert the value in attribute 'ContentTemplate' to object of type 'System.Windows.DataTemplate'. Cannot freeze this Storyboard timeline tree for use across threads.

似乎你不能在Storyboard上进行任何数据绑定(至少在.net 3.5下)。因此,我通过附加属性只定义了预期实现支持故事板完成通知的接口的资源的字符串名称来解决这个问题。

<Storyboard x:Key="SlideAnimation" local:EventCommand.StoryboardCompletedHandler="Locator">

如果有人知道在.net 3.5下处理这种情况的更好方法,我会很高兴听到。