在 WebView2 中触发 onbeforeunload
Posted
技术标签:
【中文标题】在 WebView2 中触发 onbeforeunload【英文标题】:Triggering onbeforeunload in WebView2 【发布时间】:2021-07-19 21:29:12 【问题描述】:这个answer 展示了如何通过以下方式在WebBrowser 控件中触发onbeforeunload 事件:
protected override void OnFormClosing(FormClosingEventArgs e)
if (!this.formsWebBrowser.IsDisposed)
//// Generate SHDocVw.dll: Visual Studio Developer Command Prompt "tlbimp.exe ieframe.dll /out: C:\temp\SHDocVw.dll",
var activeX = this.formsWebBrowser.ActiveXInstance;
var input = Type.Missing;
object leavePage = true;
((SHDocVw.WebBrowser)activeX).ExecWB(
SHDocVw.OLECMDID.OLECMDID_ONUNLOAD,
SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT,
ref input,
ref leavePage);
if (!(bool)leavePage)
e.Cancel = true;
return;
base.OnFormClosing(e);
但现在尝试使用 WebView2 控件从 IE11(WebBrowser 使用)迁移到 Edge Chromium,我不知道如何在 WebView2 中做同样的事情。
将 WebView2 导航到另一个页面时,对话框正确显示。 当用户关闭应用程序或包含 WebView2 的窗口时,就会出现问题。 然后它只是关闭而不显示任何对话框。
这就是上面代码对 WebBrowser 控件所做的事情,当关闭应用程序时,IE11 浏览器中会触发 (on)beforeonload 事件并返回一个布尔值。如果用户按下“离开”或没有激活 beforeonload 事件,则为 true;如果用户按下“留在页面上”,则为 false。
缺少调用 ExecuteScriptAsync("onbeforeunload();") (使用 window.addEventListener("beforeunload", function(event) 设置事件时不起作用。 .. );) 如何在 WebView2 中做同样的事情?
编辑:
问题是我不想在关闭时总是显示对话框,除非我真的必须这样做。
我只想在页面有未保存的更改时显示它(并且它在 javascript 中的 beforeunload
事件中传达了这一点)。
我知道如何在 C# 代码中处理该问题的唯一方法是触发内置的onunload
事件,在浏览器中显示beforeunload
对话框。
这正是 ActiveXInstance.ExecWB(OLECMDID_ONUNLOAD)
对 WebBrowser 控件和 IE11 所做的。
可能根本不可能以相同的方式在 WebView2/Chromium 中触发该事件?这就是我要问的。
我尝试在 FormClosing
事件中调用 JavaScript,但应用程序只是关闭而不等待响应。
我想唯一的其他选择是删除 x-close 按钮并使用自定义关闭按钮,该按钮可以进行所需的检查,然后关闭应用程序。
【问题讨论】:
在beforeunload
事件中告诉我们你想做什么,然后我们可以给你一个更好的答案(一般beforeunload
应该避免)。 Edge 中没有 activeX,所以你不能使用代码,你显示。
你不能简单地使用FormClosing
事件吗?
【参考方案1】:
这对我有用。您可以将其与表单关闭或其他内容结合使用。不要忘记在适当的地方正确分离事件/处置。这只是一个示例。
public partial class Form2 : Form
public Form2()
InitializeComponent();
private void Form2_Load(object sender, EventArgs e)
DoWork();
private async Task DoWork()
await webView21.EnsureCoreWebView2Async();
webView21.CoreWebView2.Settings.AreDefaultScriptDialogsEnabled = false;
webView21.CoreWebView2.ScriptDialogOpening += CoreWebView2_ScriptDialogOpening;
await webView21.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.addEventListener('beforeunload', function(e) return event.returnValue = 'prompt';);");
webView21.Source = new Uri("https://www.google.com");
private void CoreWebView2_ScriptDialogOpening(object sender, Microsoft.Web.WebView2.Core.CoreWebView2ScriptDialogOpeningEventArgs e)
if (MessageBox.Show("do you want to leave", "Leave?", MessageBoxButtons.OKCancel) == DialogResult.OK)
e.Accept();
else
e.GetDeferral();
【讨论】:
感谢您的回答,但这只是替换了现有的内置对话框。并且在关闭表单时不起作用,因为此时无法调用页面来触发对话框,这就是为什么我需要一种方法来触发浏览器的对话框。 e.GetDeferral();也只是推迟事件并冻结浏览器,直到在 Deferral 上调用 Complete()。以上是关于在 WebView2 中触发 onbeforeunload的主要内容,如果未能解决你的问题,请参考以下文章