首先说些题外话,很久没有写博客了,空间里面的大部分文章还是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. day 93 Django学习之django自带的contentType表

    Django学习之django自带的contentType表   通过django的contentType表来搞定一个表里面有多个外键的简单处理: 摘自:https://blog.csdn.net/a ...

  2. Oracle之子程序(存储过程、方法、包)

    .过程[存储过程] CREATE [OR REPLACE] PROCEDURE <procedure name> [(<parameter list>)] IS|AS < ...

  3. Flume(2)-拓扑结构与Agent内部原理

    一. 拓扑结构 1. 串行模式 这种模式是将多个flume给顺序连接起来了,从最初的source开始到最终sink传送的目的存储系统.此模式不建议桥接过多的flume数量, flume数量过多不仅会影 ...

  4. Ubuntu16.04安装TFTP服务,完成开发板下载文件

    1.安装TFTP服务 $ sudo apt-get install tftp-hpa tftpd-hpa 2.建立传递目录 $ mkdir tftp $ sudo chmod 777 tftp/ -R ...

  5. 20155236 《Java程序设计》实验四(Android程序设计)实验报告

    20155236 <Java程序设计>实验四(Android程序设计)实验报告 一.实验内容及步骤 第24章:初识Android 任务一:完成Hello World, 要求修改res目录中 ...

  6. 2016-2017-2 20155325实验二《Java面向对象程序设计》实验报告

    实验二 面向对象程序设计-1 答案截图 码云代码链接 链接1 实验遇到的问题和解决过程 问题1:在plugins里搜索不到JUnitGenerator V2.0只能搜到Generste Teats 问 ...

  7. EXCEL 处理重复数据名字后面追加值

    近期要用 EXCEL 处理重复数据名字后面追加值的,如图: 先排序,再根据条件追加 [公式]=+B6&IF(COUNTIF($B$6:B6,B6)-1>0,"_" & ...

  8. 服务端调用接口API利器之HttpClient

    前言 之前有介绍过HttpClient作为爬虫的简单使用,那么今天在简单的介绍一下它的另一个用途:在服务端调用接口API进行交互.之所以整理这个呢,是因为前几天在测试云之家待办消息接口的时候,有使用云 ...

  9. day1 RHCE

    1.环境部署 classroom.example.com: 172.25.0.254 root Asimov server0.example.com: 172.25.0.11 root redhat ...

  10. MySQL数据库之安装,基本操作

    一.基础部分 1.数据库是什么 之前所学,数据要永久保留,比如用户注册的用户信息,都是保存于文件,而文件只能存在于某一台机器上. 如果我们不考虑从文件中读取数据的效率问题,并且假设我们的程序所有的组件 ...