今天在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>