WebView2 - 拦截和阻止/取消锚点导航



在我的WinForms应用程序中,我使用WebView2来显示节俭派对内容。 当用户单击 webView 内的链接(或其他导航元素)时,应在默认浏览器(而不是 webView 中)打开目标链接。 在大多数情况下,我能够通过NewWindowRequestedNavigationStarting事件实现所需的行为。 但是对于当前页面(<a href="#my_anchor">)内的锚导航,这些事件不会触发。

有一个SourceChanged事件,如果在锚导航中触发,它甚至允许通过检查来确定这是in-page导航IsNewDocument,但它不允许取消导航。

我正在考虑基于 js 的解决方案,例如订阅所有a标签的click事件,甚至是通过进一步过滤订阅整个document的事件。但我意识到这样的解决方案在许多非平凡的情况下都行不通,包括

  • 动态创建的a元素
  • 键盘导航(TAB 键选择链接,Enter 启动操作,因此没有click事件)
  • 元素
  • 内部有很多元素(img等)并且用户单击此类内部元素的情况a
  • 使用 JS 启动导航时

那么,是否存在处理和取消任何导航(包括当前页面中的锚点)的方法?

我也有同样的要求。 我使用的是 Win32 C++,对我来说,NewWindowRequest 事件确实在锚点导航上触发,我添加了此实现以取消默认行为并在默认浏览器中打开 Uri...

// Register a handler for the NewWindowRequested event.
CHECK_FAILURE(m_webView->add_NewWindowRequested(
Callback<ICoreWebView2NewWindowRequestedEventHandler>(
[this](ICoreWebView2* sender, ICoreWebView2NewWindowRequestedEventArgs* args) {
// get the target Uri
LPWSTR sUri;
CHECK_FAILURE(args->get_Uri(&sUri));
// and if it was user initiated (e.g. click on an anchor tag)
BOOL bUserInit;
CHECK_FAILURE(args->get_IsUserInitiated(&bUserInit));
if (bUserInit) {
// cancel default behaviour
args->put_Handled(TRUE);
// and open Uri in default browser
ShellExecute(0, 0, sUri, 0, 0, SW_SHOW);
}
return S_OK;
})
.Get(), nullptr));

我也遇到了这个问题,作为解决方法,我做了这个:

//MainWindow.xaml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="MainWindow" 
x:Class="WebBrowser.MainWindow"
mc:Ignorable="d"
FontSize="14" Title="WebView2 Test" Width="400" Height="400" WindowStartupLocation="Manual"
SizeToContent="Manual" Cursor="Wait"
WindowStyle="None" ResizeMode="NoResize" PreviewKeyDown="AdvertisementWindow_PreviewKeyDown">
<DockPanel>
<wv2:WebView2 Name="myWebBrowser"/>
</DockPanel>
</Window>

MainWindow.xaml.cs源代码

using System.Windows;
using System.Windows.Input;
using Microsoft.Web.WebView2.Core;
namespace WebBrowser
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private string url = "https://en.wikipedia.org/wiki/Hyperlink";
public MainWindow()
{
InitializeComponent();
InitializeAsync();
myWebBrowser.NavigationStarting += MyWebBrowser_NavigationStarting;
myWebBrowser.SourceChanged += MyWebBrowser_SourceChanged;
}
private void MyWebBrowser_SourceChanged(object sender, CoreWebView2SourceChangedEventArgs e)
{
string uri = myWebBrowser.Source.ToString();
if (e.IsNewDocument == false && uri.EndsWith("#Further_reading"))
{
MessageBox.Show("You clicked #Further_reading", "Further Reading");
}
}
async void InitializeAsync()
{
await myWebBrowser.EnsureCoreWebView2Async(null);
myWebBrowser.CoreWebView2.Navigate(url);
}

private void AdvertisementWindow_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if(e.Key == Key.Escape)
{
Close();
}
}
private void MyWebBrowser_NavigationStarting(object sender, Microsoft.Web.WebView2.Core.CoreWebView2NavigationStartingEventArgs e)
{
//cancel the current event
if (!e.Uri.ToString().StartsWith(url))
{
e.Cancel = true;
System.Diagnostics.Process.Start(e.Uri.ToString());
}
}
}
}

此代码应在外部浏览器(默认系统浏览器)中打开每个链接,并且外部页面的锚点也将在外部浏览器中打开。所以这意味着我们取消在 WebView 中的导航(e.Cancel = True)。关于同一站点的锚点,我们可以在 SourceChanged 事件中处理它们,并且我们不需要停止导航,因为它将保持在同一页面上。

相关内容

  • 没有找到相关文章

最新更新