Создавайте вкладки с помощью WebView2 - Edge
Предоставьте фрагмент кода для создания вкладки вместо открытия страницы в новом окне при нажатии на ссылки в форме окна webview2 - Edge в C#.
Выполнили следующие шаги.
Перетащите элемент управления webview2 в форму Windows C# и обновите ссылку на исходное свойство: https://example.com/
Сайт https://example.com/ успешно открыт в webview2
нажмите на несколько ссылок на сайте - https://example.com/, и он откроет новое окно и ищет, чтобы открыть это в новой вкладке, а не открывать его в новом окне
Это событие webView.CoreWebView2.NewWindowRequested никогда не срабатывает при отладке кода. В случае, если это событие webView.CoreWebView2.NewWindowRequested возникло, тогда метод навигации недоступен в классе webview, а он доступен в классах corewebview2 и получает исключение нулевой ссылки, если мы его используем.
2 ответа
Для полноты картины я смог добиться того же благодаря объяснению Дэвида Рисни. К сожалению, в нем не было никакого кода, но я добился этого, используя
1.0.721-prerelease
а также
Microsoft.WebView2.FixedVersionRuntime.87.0.664.66.x64
:
Программа.cs:
using System;
using System.Windows.Forms;
namespace TestApp1
{
static class Program
{
public static Microsoft.Web.WebView2.Core.CoreWebView2Environment WebView2Environment;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
Форма1.cs:
using System;
using System.Windows.Forms;
namespace TestApp1
{
public partial class Form1 : Form
{
public Microsoft.Web.WebView2.Core.CoreWebView2Deferral Deferral;
public Microsoft.Web.WebView2.Core.CoreWebView2NewWindowRequestedEventArgs Args;
public Form1()
{
InitializeComponent();
webView21.CoreWebView2InitializationCompleted += webView21_CoreWebView2InitializationCompleted_1;
}
private void CoreWebView2_NewWindowRequested(object sender, Microsoft.Web.WebView2.Core.CoreWebView2NewWindowRequestedEventArgs e)
{
Form1 f = new Form1();
f.Args = e;
f.Deferral = e.GetDeferral();
f.Show();
}
private async void Form1_Load(object sender, EventArgs e)
{
if (Program.WebView2Environment == null)
Program.WebView2Environment = Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(@"C:\Users\Dragon\Downloads\Microsoft.WebView2.FixedVersionRuntime.87.0.664.66.x64", $@"C:\Users\Dragon\Desktop\Test{Guid.NewGuid()}").Result;
await webView21.EnsureCoreWebView2Async(Program.WebView2Environment);
webView21.Source = new Uri("http://www.google.com");
}
private void webView21_CoreWebView2InitializationCompleted_1(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
{
if (!e.IsSuccess) { MessageBox.Show($"{e.InitializationException}"); }
if (Deferral != null)
{
Args.NewWindow = webView21.CoreWebView2;
Deferral.Complete();
}
webView21.CoreWebView2.NewWindowRequested += CoreWebView2_NewWindowRequested;
}
private void button1_Click(object sender, EventArgs e)
{
webView21.ExecuteScriptAsync($@"window.open('http://www.bing.com', '_blank');");
}
}
}
Так что это работает довольно странно: чтобы создать новое окно, вы можете сделать это через JavaScript, используя
ExecuteScriptAsync
. В этом случае я открываю новое окно для bing.com. Таким образом, это вызывает вызов
CoreWebView2_NewWindowRequested
. Чтобы событие прошло и код заработал (иначе он зависнет) он должен пройти все это. Таким образом, вы не можете установить свойство
CoreWebView2NewWindowRequestedEventArgs
внутри события, которое происходит в данный момент.
Решение состоит в том, чтобы перевести данные события (args & deferral) в новую форму, показать их, а при загрузке и после того, как свойство элемента управления не равно нулю/инициализировалось, путем вызова
CoreWebView2InitializationCompleted
, проверьте, не являются ли args/deferral нулевыми, а затем вызовите отсрочку как
Complete()
(это в основном похоже на обещание JS) И здесь вы можете установить
NewWindow
собственность как
CoreWebView2
был инициализирован и, следовательно, не равен нулю.
Надеюсь, это ответит на ваш вопрос и будущих читателей. С этим кодом я смог заставить его работать.
В WebView2 нет встроенной поддержки вкладок. Однако вы можете перехватить новые окна с помощью события NewWindowRequested и предоставить свой собственный CoreWebView2 в качестве этого нового окна и разместить этот CoreWebView2 в своем пользовательском интерфейсе так, как вам нравится. Например, новый CoreWebView2 можно разместить в пользовательском интерфейсе, чтобы он выглядел как новая вкладка. (Похоже, что вы делаете именно это, но явно декларируете это здесь, чтобы убедиться, что я правильно понимаю ваш сценарий.)
Что касается нулевого свойства WebView2.CoreWebView2, вы можете вызвать EnsureCoreWebView2Async и дождаться возвращенной задачи или вы можете установить свойство WebView2.Source и дождаться отправки события CoreWebView2Ready, чтобы свойство WebView2.CoreWebView2 было заполнено. Его значение null перед который.
Кроме того, если вам нужно заставить CoreWebView2 заполнить свойство NewWindowRequestedEventArg NewWindow, поскольку указанные выше шаги для получения CoreWebView2 из экземпляра WebView2 являются асинхронными, вам необходимо вызвать метод GetDeferralNewWindowRequestedEventArg перед запуском асинхронной работы в NewWindowRequested. обработчик событий и вызовите Complete в Deferral после того, как ваша асинхронная работа будет выполнена в обработчике событий NewWindowRequested.
Если вы обнаружите случаи, когда WebView2 открывает новые окна, но событие NewWindowRequested не запускается, пожалуйста, откройте страницу об ошибках на https://github.com/MicrosoftEdge/WebViewFeedback. Какую версию SDK и браузер вы используете с WebView2? В настоящее время исправлены некоторые ошибки, при которых в некоторых сценариях открытие новых окон не запускает событие NewWindowRequested.