更新与 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 后,当上面连接 Completed 事件的代码运行时,我收到以下错误:
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 下处理这种情况的更好方法,我会很高兴听到。