首先说些题外话,很久没有写博客了,空间里面的大部分文章还是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 的网页通信。可以通过检索 BrowserInteropHelperHostScript 属性来完成此操作。此属性会返回一个代表该 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代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<meta http-equiv="X-UA-Compatible" content="IE=8"/> <!--不加上这一句,IE9貌似没效果-->
<script type="text/javascript">
// 调用WPF的JS函数
function JSInvokeWPF() {
if (wpfObj == null) {
alert("中间对象为空!");
} else {
alert(wpfObj.MyMethod("JS调用WPF后台函数"));
}
} // 供WPF调用的函数
function WPFInvokeJS(parameter) {
alert(parameter);
}
var wpfObj = null;
function SetWpfObj(obj) {
wpfObj = obj;
} </script> <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>交互测试</title>
</head>
<body>
<span>
<button title="JS调用WPF函数" style="height: 30px; width: 100%;" onclick=" JSInvokeWPF();return false; ">JS调用WPF函数</button>
</span>
<iframe id="wpf" src="OPSYS.Web_Schematic.UI.xbap" Style="width: 100%;height: 540px" ></iframe>
</body>
</html>

WPF后台文件代码如下:

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;
}
}
}

运行结果如下:

如果您发现VS老是报JS函数不存在,请设置如下内容(请运行在IE8模式):

WPF浏览器应用程序与JS的互调用(不用WebBrowser)的更多相关文章

  1. 如何使Wpf浏览器应用程序被完全信任运行

    原文地址链接:http://blogs.microsoft.co.il/maxim/2008/03/05/how-to-run-wpf-xbap-as-full-trust-application/ ...

  2. 一步一步部署WPF浏览器应用程序

    WPF浏览器应用程序与Silverlight,Asp.net相比,同是发布到服务器,在IE中运行.WPF浏览器应用程序部署起来却相对困难. 相信很多朋友在第一次部署WPF浏览器应用程序时,都遇到&qu ...

  3. WPF ClickOnce应用程序IIS部署发布攻略

    WPF程序非常适合公司内网使用,唯一缺点就是客户端要安装.net框架4.0.优势也很明显,在客户端运行的是一个WinForm程序,自动下载,可以充分利用客户机的性能,而且是以当前的Windows用户权 ...

  4. 6个可以隐藏运行bat,浏览器等程序的方法

    在电脑启动时或者设置时间时运行指定的程序很容易实现.但是有时候还需要运行时不显示主界面,隐藏到后台运行.比如:开机时一段Bat批处理执行删除默认共享; 开机自动运行浏览器隐藏到后代打开指定网页等,希望 ...

  5. 转《在浏览器中使用tensorflow.js进行人脸识别的JavaScript API》

    作者 | Vincent Mühle 编译 | 姗姗 出品 | 人工智能头条(公众号ID:AI_Thinker) [导读]随着深度学习方法的应用,浏览器调用人脸识别技术已经得到了更广泛的应用与提升.在 ...

  6. 用于浏览器本地存储的js插件 - jStorage

    简介 jStorage是一个跨浏览器的将key-value类型的数据存储到浏览器本地存储的js插件——jStorage支持所有主流浏览器,PC机(甚至包括是IE6)和移动终端均可用.此外,jStora ...

  7. 微信小程序の微信js

    一.Javascript简介 二.nodejs中的jscript nodejs表示谷歌基于v8引擎的一门后端语言, ECMA表示ECMA262标准的基本js,native表示nodejs本身的一些包, ...

  8. 深入浏览器工作原理和JS引擎(V8引擎为例)

    浏览器工作原理和JS引擎 1.浏览器工作原理 在浏览器中输入查找内容,浏览器是怎样将页面加载出来的?以及JavaScript代码在浏览器中是如何被执行的? 大概流程可观察以下图: 首先,用户在浏览器搜 ...

  9. iOS开发UI篇—简单的浏览器查看程序

    iOS开发UI篇—简单的浏览器查看程序 一.程序实现要求 1.要求 2. 界面分析 (1) 需要读取或修改属性的控件需要设置属性 序号标签 图片 图片描述 左边按钮 右边按钮 (2) 需要监听响应事件 ...

随机推荐

  1. Hadoop的版本演变

    Hadoop版本演变 Apache Hadoop的四大分支构成了三个系列的Hadoop版本: 0.20.X系列 主要有两个特征:Append与Security 0.21.0/0.22.X系列 整个Ha ...

  2. firefox burp ssl证书配置

    打开浏览器 设置->证书->证书频发机构->添加证书 添加成功->找到位置->编辑信任->信任->查看证书 导出-> win下可直接安装证书->受 ...

  3. uva 156 - Ananagrams (反片语)

    csdn:https://blog.csdn.net/su_cicada/article/details/86710107 例题5-4 反片语(Ananagrams,Uva 156) 输入一些单词,找 ...

  4. go_json解析

    总结: 其他类型转json func Marshal(v interface{}) ([]byte, error)  json 转其他类型 func Unmarshal(data []byte, v ...

  5. 数据结构与算法之排序(2)选择排序 ——in dart

    选择排序的算法复杂度与冒泡排序类似,其比较的时间复杂度仍然为O(N2),但减少了交换次数,交换的复杂度为O(N),相对冒泡排序提升很多.算法的核心思想是每次选出一个最小的,然后与本轮循环中的第一个进行 ...

  6. 脱离matlab运行可执行程序的步骤

    MCR是由matlab的运行环境,占用不到600M的对于用不同matlab版本生成的exe文件,MCR版本也会有不同,因此,在程序打包时,最好将相应版本的MCR一起打包.MCR环境的设置文件存放目录如 ...

  7. 20155215 2016-2017-2《Java程序设计》课程总结

    20155215 2016-2017-2<Java程序设计>课程总结 一.(按顺序)每周作业链接汇总 预备作业1: 对于JAVA课程本身的期望和理解.以及期望的师生关系是什么样的,自己印象 ...

  8. 20145209 2016-2017-2 《Java程序设计》课程总结

    20145209 2016-2017-2 <Java程序设计>课程总结 每周作业链接汇总 预备作业01 http://www.cnblogs.com/liuyiyang/p/6194319 ...

  9. 用sudo 运行命令的时候,环境变量用的是super用户的环境变量

    比如今天在~/.bashrc设置了JAVA_HOME, 而sudo运行命令的时候却显示没有设置可用的JAVA_HOME

  10. Java技术——Interface与abstract类的区别

    )抽象类是对类抽象,是面向整个类的自下而上的设计理念,一般是先有各种子类,再有把这些有关系的子类加以抽象为父类的需求.而接口是对行为的抽象,是面向行为的自上而下的设计理念,接口根本就不需要知道子类的存 ...