我正在使用webBrowser.Document.InvokeScript("Function")
运行javascript,它位于使用Winforms WebBrowser打开的本地文件中。
问题是,我需要javascript才能继续执行。我该如何等待/倾听?
这是我的C#代码:
private void Button1_ItemClick_1(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
webBrowser.Document.InvokeScript("Script_A");
Method_A();
DialogResult = System.Windows.Forms.DialogResult.OK;
}
Javascript代码:
<script>function Script_A() { Script_B(); }</script>
如何在Script_B完成之前确保没有执行Method_A?
答案 0 :(得分:7)
使用async / await,您可以等到脚本执行而不会阻止UI。
public async void AMethod()
{
string script =
@"<script>
function Script_A() {
Script_B();
window.external.Completed(); //call C#: CallbackObject's Completed method
}
function Script_B(){
alert('in script');
}
</script>";
TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
webBrowser1.ObjectForScripting = new CallbackObject(tcs);
//Ensure DocumentText is loaded before invoking "InvokeScript",
//by extension method "SetDocumentTextAsync" (below)
await webBrowser1.SetDocumentTextAsync(script);
webBrowser1.Document.InvokeScript("Script_A");
await tcs.Task;
MessageBox.Show("Script executed");
}
[ComVisible(true)]
public class CallbackObject
{
TaskCompletionSource<bool> _tcs = null;
public CallbackObject(TaskCompletionSource<bool> tcs)
{
_tcs = tcs;
}
public void Completed()
{
_tcs.TrySetResult(true);
}
}
public static class BrowserExtensions
{
public static Task SetDocumentTextAsync(this WebBrowser wb, string html)
{
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
WebBrowserDocumentCompletedEventHandler completedEvent = null;
completedEvent = (sender, e) =>
{
wb.DocumentCompleted -= completedEvent;
tcs.SetResult(null);
};
wb.DocumentCompleted += completedEvent;
wb.ScriptErrorsSuppressed = true;
wb.DocumentText = html;
return tcs.Task;
}
}
答案 1 :(得分:0)
你需要实现一个回调方法(不要遗忘ComVisible-Attribute
)你将使用
window.mymethod();
这样,你实际上需要分开&#39;你的方法。
Here是来自SO的好文章。
here是一个教程:
从WebBrowser中托管的JavaScript调用C#方法
AspDotNetDev,2011年5月6日
此示例演示如何从JavaScript调用C#。它还显示参数可以传递给C#方法。
首先,创建一个Windows窗体应用程序。然后,将WebBrowser控件添加到窗体。然后修改表单的代码,使其如下所示:
namespace WindowsFormsApplication6
{
// This first namespace is required for the ComVisible attribute used on the ScriptManager class.
using System.Runtime.InteropServices;
using System.Windows.Forms;
// This is your form.
public partial class Form1 : Form
{
// This nested class must be ComVisible for the JavaScript to be able to call it.
[ComVisible(true)]
public class ScriptManager
{
// Variable to store the form of type Form1.
private Form1 mForm;
// Constructor.
public ScriptManager(Form1 form)
{
// Save the form so it can be referenced later.
mForm = form;
}
// This method can be called from JavaScript.
public void MethodToCallFromScript()
{
// Call a method on the form.
mForm.DoSomething();
}
// This method can also be called from JavaScript.
public void AnotherMethod(string message)
{
MessageBox.Show(message);
}
}
// This method will be called by the other method (MethodToCallFromScript) that gets called by JavaScript.
public void DoSomething()
{
// Indicate success.
MessageBox.Show("It worked!");
}
// Constructor.
public Form1()
{
// Boilerplate code.
InitializeComponent();
// Set the WebBrowser to use an instance of the ScriptManager to handle method calls to C#.
webBrowser1.ObjectForScripting = new ScriptManager(this);
// Create the webpage.
webBrowser1.DocumentText = @"<html>
<head>
<title>Test</title>
</head>
<body>
<input type=""button"" value=""Go!"" onclick=""window.external.MethodToCallFromScript();"" />
<br />
<input type=""button"" value=""Go Again!"" onclick=""window.external.AnotherMethod('Hello');"" />
</body>
</html>";
}
}
}
请注意,您的应用程序可能是WindowsFormsApplication6以外的命名空间的一部分,但如果您明确遵循上述说明,其余代码应该可以正常工作。我创建了这个提示/技巧,因为有人问我一个问题,他们并不理解我发送给他们的这个样本。这个提示/技巧通过修复我发现的两个错误,添加了未提及的使用语句,并通过大量注释代码,使样本更容易理解。希望你们其他人也会发现这个用途。 许可证