WPF与Javascript交互

今天在WPF中使用WebBrowser的InvokeScript方法与Javascript交互时遇到若干问题,记录如下:

  • 使用[ComVisible(true)] 标记公开给脚本访问的对象
  • 调用InvokeScript方法一定要在WebBrowser LoadCompleted后调用
  • 使用 function 申明后台需要调用的方法
  • 返回COMException表明调用脚本函数未找到

HTML:demo.htm

<!DOCTYPE>

<html>

<head>

<meta charset="utf-8" />

<title></title>

</head>

<body>

<input type="button" onclick="window.external.say('this is from htm');return false;" value="调用后方法" />

<div ></div>

<script type="text/javascript">

(function (window) {

var searcher = {

showmsg: function (msg) {

alert(msg);

}

};

window.searcher = searcher;

})(window);

function showmsg(msg) {

searcher.showmsg(msg);

}

</script>

</body>

</html>

WPF:MainWindow.xaml

<Grid >

<Grid.RowDefinitions>

<RowDefinition Height="50"/>

<RowDefinition Height="*"/>

</Grid.RowDefinitions>

<Border BorderBrush="BlueViolet" BorderThickness="0,0,0,1">

<StackPanel Orientation="Horizontal">

<Button x:Name="btn1" Width="100" Height="40" Click="btn1_Click" Content="加载页面" VerticalAlignment="Center" Margin="10,0"></Button>

<Button x:Name="btn2" Width="100" Height="40" Click="btn2_Click" Content="调用脚本" VerticalAlignment="Center"></Button>

</StackPanel>

</Border>

<WebBrowser x:Name="webBrowser" Grid.Row="1"></WebBrowser>

</Grid>

后台代码如下:

/// <summary>

/// Web.xaml 的交互逻辑

/// </summary>

public partial class Web : Window

{

public Action webHandler;

public Web()

{

InitializeComponent();

this.webBrowser.ObjectForScripting = new ScriptObject(this);

this.webBrowser.LoadCompleted += new System.Windows.Navigation.LoadCompletedEventHandler(webBrowser_LoadCompleted);

}

void webBrowser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)

{

if (this.webHandler != null)

{

this.webHandler();

this.webHandler = null;

}

}

private void btn1_Click(object sender, RoutedEventArgs e)

{

this.webHandler = () =>

{

this.webBrowser.InvokeScript("showmsg", new object[] { "{'center':{'lng':12.232,'lat':13.232},'zoom':14}" });

};

string htmlfile = System.IO.Path.Combine("file:///", System.Environment.CurrentDirectory, "Resources/demo.htm");

this.webBrowser.Navigate(new Uri(htmlfile, UriKind.RelativeOrAbsolute));

}

private void btn2_Click(object sender, RoutedEventArgs e)

{

this.webBrowser.InvokeScript("showmsg", new object[] { "{'center':{'lng':12.232,'lat':13.232},'zoom':14}" });

}

}

[ComVisible(true)]

public class ScriptObject

{

private Window instance;

public ScriptObject(Window instance)

{

this.instance = instance;

}

public void say(string msg)

{

MessageBox.Show(msg, "来自服务端的消息", MessageBoxButton.OK, MessageBoxImage.Information);

}

}

从cs调用js失败的情况(一直没有找到问题的原因):

cs:

InvokeScript("searcher.showmsg", new object[] { "hello" })

js:

<script type="text/javascript">

(function (window) {

var searcher = {

showmsg: function (msg) {

alert(msg);

}

};

window.searcher = searcher;

})(window);

</script>