WPF浏览器应用程序与JS的互调用(不用WebBrowser)
2014-01-17 11:50
337 查看
首先说些题外话,很久没有写博客了,空间里面的大部分文章还是11年写的。那时候刚毕业就来到这家公司,参与到一个Asp.net MVC的项目开发中,这个项目是一个全新的项目,连项目开发框架都没有,亏得领导的信任,让我研究一个MVC开发框架。那时候的我就像打了鸡血一样斗志高昂,努力奋斗了一个月后终于搭建了一个比较粗糙的Asp.net MVC+JQuery+EF4.0+Oracle的开发框架,不得不说MVC和Jquery Ajax简直就是天生一对。空间中的文章大部分都是这个时候写的。
随后的两年,我投入到基于WPF的逻辑图项目的研发中,学习到了很多东西,业务上的就不说了;技术上包括:如何利用WPF的图形渲染优势开发一套图形引擎、通用的撤销回做组件设计、图形布局算法(花了大量的时间)、鼠标工具、图形拓扑分析联动等。由于技术保密原因,这些东西都不能写成博客公开,因此这两年我一篇博客都没写。但是最近需要开发一个WPF浏览器应用程序与外部Flex程序的交互功能,查找了很多资料都没有找到解决办法,一般都是通过WebBrowser来中转实现,这局限性不能满足要求,所以最终还是采取了JS直接与WPF函数互调用的方式来实现。
言归正传,以下是这个问题的解决方案,希望各位不吝指教。
WPF浏览器应用程序(xbap)实际并不是一个标准的Web应用程序,它只不是由IE中承载的PresentationHost.exe充当宿主来解析执行,原理与ActiveX类似。JS与ActiveX交互的资料网上很多,把WPF浏览器应用程序封装成ActiveX然后开发与JS的交互函数,这也可以作为我们的一种解决方案。但是我觉得这种办法太复杂了,所以没有采用。
“应用程序承载到 HTML 框架中后,您可以与包含 XBAP 的网页通信。可以通过检索 BrowserInteropHelper 的 HostScript 属性来完成此操作。此属性会返回一个代表该 HTML 窗口的脚本对象。然后,您可以使用常规的点语法访问 window object(window 对象)的属性、方法和事件。您还可以访问脚本方法和全局变量”
上面是msdn上的一段说明,参照上面的做法:我创建了一个html页面,然后在页面中添加一个iframe,iframe的src属性指向目标xbap文件。我们确实可以在WPF的页面后台代码中取到外面html的HostScript脚本对象,并且可以通过这个脚本对象获取html页面的控件属性甚至调用它的JS函数。但是这个对象是只读的,也就是说你别想通过这个对象给外面的Html添加一个函数、事件监听什么的。
我们的问题卡在这里了,我们已经实现了WPF调用html页面的JS函数,但是JS函数怎么样才能调用到WPF的函数呢?
其实思路很简单,我在外面的html页面的JS部分定义一个变量wpfObj,并且定义一个设置wpfObj值的函数——SetWpfObj(wpfobj);然后在wpf页面后台构造函数中通过HostScript调用SetWpfObj函数给wpfObj复制一个C#对象,由这个对象来负责调用WPF的函数;最后JS函数执行的时候通过wpfObj调用C#对象的函数便完成了JS调用WPF函数的过程。
通过这两种方式的结合,便完成了JS和WPF函数的互调用,而且简单易复用,当我需要与外部交互的时候,我给外部展示这个html;当我不需要这个接口的时候,我直接展示这个xbap即可。无图无真相,下面详细贴出代码设置和运行结果。
html代码如下:
View Code
运行结果如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/06/6614b16c7558e724bee9ef0da6121978.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/06/849ff7f83f5337f38a631ed53568126c.png)
如果您发现VS老是报JS函数不存在,请设置如下内容(请运行在IE8模式):
随后的两年,我投入到基于WPF的逻辑图项目的研发中,学习到了很多东西,业务上的就不说了;技术上包括:如何利用WPF的图形渲染优势开发一套图形引擎、通用的撤销回做组件设计、图形布局算法(花了大量的时间)、鼠标工具、图形拓扑分析联动等。由于技术保密原因,这些东西都不能写成博客公开,因此这两年我一篇博客都没写。但是最近需要开发一个WPF浏览器应用程序与外部Flex程序的交互功能,查找了很多资料都没有找到解决办法,一般都是通过WebBrowser来中转实现,这局限性不能满足要求,所以最终还是采取了JS直接与WPF函数互调用的方式来实现。
言归正传,以下是这个问题的解决方案,希望各位不吝指教。
WPF浏览器应用程序(xbap)实际并不是一个标准的Web应用程序,它只不是由IE中承载的PresentationHost.exe充当宿主来解析执行,原理与ActiveX类似。JS与ActiveX交互的资料网上很多,把WPF浏览器应用程序封装成ActiveX然后开发与JS的交互函数,这也可以作为我们的一种解决方案。但是我觉得这种办法太复杂了,所以没有采用。
“应用程序承载到 HTML 框架中后,您可以与包含 XBAP 的网页通信。可以通过检索 BrowserInteropHelper 的 HostScript 属性来完成此操作。此属性会返回一个代表该 HTML 窗口的脚本对象。然后,您可以使用常规的点语法访问 window object(window 对象)的属性、方法和事件。您还可以访问脚本方法和全局变量”
上面是msdn上的一段说明,参照上面的做法:我创建了一个html页面,然后在页面中添加一个iframe,iframe的src属性指向目标xbap文件。我们确实可以在WPF的页面后台代码中取到外面html的HostScript脚本对象,并且可以通过这个脚本对象获取html页面的控件属性甚至调用它的JS函数。但是这个对象是只读的,也就是说你别想通过这个对象给外面的Html添加一个函数、事件监听什么的。
我们的问题卡在这里了,我们已经实现了WPF调用html页面的JS函数,但是JS函数怎么样才能调用到WPF的函数呢?
其实思路很简单,我在外面的html页面的JS部分定义一个变量wpfObj,并且定义一个设置wpfObj值的函数——SetWpfObj(wpfobj);然后在wpf页面后台构造函数中通过HostScript调用SetWpfObj函数给wpfObj复制一个C#对象,由这个对象来负责调用WPF的函数;最后JS函数执行的时候通过wpfObj调用C#对象的函数便完成了JS调用WPF函数的过程。
通过这两种方式的结合,便完成了JS和WPF函数的互调用,而且简单易复用,当我需要与外部交互的时候,我给外部展示这个html;当我不需要这个接口的时候,我直接展示这个xbap即可。无图无真相,下面详细贴出代码设置和运行结果。
html代码如下:
using System.Runtime.InteropServices; using System.Windows; using System.Windows.Controls; using System.Windows.Interop; using MessageBox = System.Windows.MessageBox; namespace OPSYS.Web_Schematic.UI { /// <summary> /// ShellView.xaml 的交互逻辑 /// </summary> public partial class ShellView : Page { private dynamic scriptObject = null; public ShellView() { InitializeComponent(); // Retrieve the script object. The XBAP must be hosted in a frame or // the HostScript object will be null. if (!BrowserInteropHelper.IsBrowserHosted) { MessageBox.Show("不满足与JS调用条件"); return; } scriptObject = BrowserInteropHelper.HostScript; if(scriptObject!=null) { scriptObject.SetWpfObj(new CallbackClass()); } } private void JavaScriptInvoke_Click(object sender, RoutedEventArgs e) { if(scriptObject!=null) scriptObject.WPFInvokeJS("WPF调用JS函数"); } } //记得加上这个特性 [ComVisible(true)] public class CallbackClass { public string MyMethod(string message) { return "来自WPF的中转函数," + message; } } }
View Code
运行结果如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/06/6614b16c7558e724bee9ef0da6121978.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/06/849ff7f83f5337f38a631ed53568126c.png)
如果您发现VS老是报JS函数不存在,请设置如下内容(请运行在IE8模式):
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/06/0c574cfd60129e5c37622c78e8c5f1f5.png)
相关文章推荐
- 不同类型的浏览器调用不同的CSS(条件CSS与JS)
- WinForm中嵌入WebBrowser,并且支持C#和JS方法的相互调用
- js windows.open 调用ajax时被一些浏览器阻止弹出窗体的解决方案
- 不用AJAX实现前台JS调用后台C#方法(小技巧)-转
- WPF浏览器应用程序
- android学习笔记---53_采用网页设计软件界面,以及使用android系统内置的浏览器,利用js调用java方法
- WPF 浏览器应用程序(page页面)如何全屏
- jquery.webcam.js实现调用摄像头拍照兼容各个浏览器
- C# 封装miniblink 使用HTML/CSS/JS来构建.Net 应用程序界面和简易浏览器
- 不用AJAX实现前台JS调用后台C#方法(小技巧)
- 用js实现根据不同的分辨率和浏览器调用不同的css文件
- 在WebBrowser控件使用js调用C#方法
- 不用js多浏览器兼容纯DIV/CSS对联漂浮广告
- 一步一步部署WPF浏览器应用程序【原创】
- WPF WebBrowser使用JavaScript调用外部方法决解方法简介
- JS判断浏览器类型和屏幕分辨率来调用不同的CSS样式
- Android调用系统应用程序(打电话,发短信,打开文件,浏览器)
- js调用浏览器打印
- 不用AJAX实现前台JS调用后台C#方法
- js浏览器调用qq聊天