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 id="msg"></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>
<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 id="msg"></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.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);
}
}
/// 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>
(function (window) {
var searcher = {
showmsg: function (msg) {
alert(msg);
}
};
window.searcher = searcher;
})(window);
</script>