Запуск перед выгрузкой в ​​WebView2

В этом ответе показано, как вызвать onbeforeunload в элементе управления WebBrowser следующим образом:

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);
}

Но теперь, пытаясь перейти от IE11 (используемого WebBrowser) к Edge Chromium с помощью элемента управления WebView2, я не могу понять, как сделать то же самое в WebView2.

Диалоговое окно отображается правильно при переходе WebView2 на другую страницу. Проблема возникает, когда пользователь закрывает приложение или окно, содержащее WebView2. Затем он просто закрывается, не показывая никакого диалога.

Вот что делает приведенный выше код для элемента управления WebBrowser: при закрытии приложения в браузере IE11 запускается событие (on) beforeonload и возвращается bool. Истина, если пользователь нажал кнопку «Выйти» или событие beforeonload не было активным, и ложь, если пользователь нажал кнопку «Оставаться на странице».

За исключением вызова ExecuteScriptAsync (onbeforeunload ();) (который не работает при установке события с помощью window.addEventListener (beforeunload, function (event) {...}); ) как то же самое можно сделать в WebView2?


Изменить:

Проблема в том, что я не хочу показывать диалог всегда при закрытии, если только в этом нет необходимости. Я хочу показать это только в том случае, если на странице есть несохраненные изменения (и он сообщает об этом в событии beforeunload в JavaScript). Единственный способ, которым я знаю, как справиться с этим в коде C #, - это запустить встроенное событие onunload, отображающее диалоговое окно beforeunload в браузере. Именно это делает ActiveXInstance.ExecWB(OLECMDID_ONUNLOAD) для элемента управления WebBrowser и IE11.

Может просто невозможно вызвать это событие в WebView2 / Chromium таким же образом? Я действительно об этом спрашиваю. Я пробовал вызывать JavaScripts в событии FormClosing, но приложение просто закрывается без ожидания ответа.

Я предполагаю, что единственный другой вариант - удалить кнопку x-close и использовать настраиваемую кнопку закрытия, которая может выполнять необходимые проверки, а затем закрывать приложение.


person Erik Bunnstad    schedule 26.04.2021    source источник
comment
Покажите нам, что вы хотите сделать на мероприятии beforeunload, тогда мы сможем дать вам лучший ответ (в общем, beforeunload следует избегать). В Edge нет activeX, поэтому вы не можете использовать код, как вы показываете.   -  person Poul Bak    schedule 26.04.2021
comment
Разве вы не можете просто использовать событие FormClosing?   -  person Poul Bak    schedule 26.04.2021


Ответы (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();
            }
        }
person Nikki9696    schedule 26.04.2021
comment
Спасибо за ответ, но это просто заменяет существующий встроенный диалог. И не работает при закрытии формы, поскольку в этот момент нет возможности вызвать страницу для запуска диалогового окна, поэтому мне нужен способ запуска диалогового окна браузера. e.GetDeferral (); также просто откладывает событие и замораживает браузер до тех пор, пока в Deferral не будет вызван Complete (). - person Erik Bunnstad; 27.04.2021