只是将其记录为问题和答案,这样其他人就不必遭受同样的痛苦。
我有一个 WPF 应用程序,可以为页面添加动画效果,就像在 iPhone 上滑动一样。一切都很好,直到其中一个页面需要包含 Web 浏览器。它对动画的 react 根本不好——当它应该滑入时,它不会出现,直到你聚焦它,而当它应该滑出时,它会消失,直到你将鼠标移到它上面。在这两种情况下,它只是弹出/弹出而不是动画。
让事情变得复杂的是,在项目期间,由于不相关的原因,决定回到 .net 3.5 而不是 4。
所以问题是:我怎样才能(a)让 WebBrowser 正确设置动画;或 (b) 如何在动画开始时隐藏 WebBrowser 并在结束时再次显示它。动画目前是在 XAML 中定义的,我并不是特别想将其更改为代码。
接下来的问题是:是否有更好的方法,仍然使用 .net 3.5?
最佳答案
更新 WPF WebBrowser 与 WinForms 相比实在是太蹩脚了,我已经使用 WindowsFormsHost 进行了交换。下面的所有内容仍然适用,但 WebBrowser 现在不再那么高贵(例如,它有一个 DocumentCompleted 事件)。
我很快就放弃了为 WebBrowser 设置动画的选项,因为它太难了,而是决定隐藏并重新显示它。动画的开始是由 View 模型上的命令触发的。然后,它找到应显示的页面,创建它,并通过反射(reflect)过渡状态的附加属性启动动画。
我创建了一个接口(interface) IRequireTransitionInfo
,这样调用 IRequireTransitionInfo.TransitioningFrom
就可以让其有机会隐藏自己,而 IRequireTransitionInfo.TransitioningTo
再次显示。 TransitioningFrom 很简单,但在 Storyboard 完成时必须调用 TransitioningTo。
最初,在 View 模型的构造函数中,它查找 Storyboard 并 Hook 到其 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 后,当上面连接 Completed 事件的代码运行时,我收到以下错误:
Specified value of type 'System.Windows.Media.Animation.Storyboard' must have IsFrozen set to false to modify.
尽管有一些其他答案,但您无法解冻卡住的 Freezable,并且将代码移动到 MainWindow 的构造函数中也没有帮助。
我沿着 Storyboard 上绑定(bind)到 View 模型上命令的附加属性的路径进行操作。
<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 上进行任何数据绑定(bind)(至少在 .net 3.5 下)。因此,我通过让附加属性仅定义资源的字符串名称来稍微不优雅地解决了这个问题,该资源预期实现支持 Storyboard完成通知的接口(interface)。
<Storyboard x:Key="SlideAnimation" local:EventCommand.StoryboardCompletedHandler="Locator">
如果有人知道在 .net 3.5 下处理这种情况的更好方法,我会很高兴听到。
关于wpf - 如何为 WPF WebBrowser 制作动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11445072/