【问题标题】:Triggering onbeforeunload in WebView2在 WebView2 中触发 onbeforeunload
【发布时间】: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事件吗?

标签: c# winforms onbeforeunload webview2


【解决方案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()。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-30
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 2020-05-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多