You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MAUI WebView无法打开外部链接,Navigating事件未触发求助

.NET MAUI WebView 外部链接点击无反应,Navigating事件不触发

问题详情

使用Visual Studio 2022开发包含WebView控件的.NET MAUI移动应用,源网站mywebsite.com加载正常,内部链接可正常工作。需求是点击外部链接(如microsoft.com)时,在手机默认浏览器打开该网站,但目前点击任何外部链接均无反应——无论HTML中target属性设为_blank还是其他值,Navigating事件都不会触发。点击mywebsite.com内部链接时,Navigating事件可正常触发,已尝试相关解决方案但无效。

代码示例

MainPage.xaml.cs

public MainPage()
{
    InitializeComponent();
    // 订阅Navigating事件
    proteoWebView.Navigating += OnNavigating;
    // 订阅Navigated事件
    proteoWebView.Navigated += OnNavigated;
}

private void OnNavigating(object sender, WebNavigatingEventArgs e)
{
    // 检查是否为外部链接
    if (!e.Url.StartsWith("https://mywebsite.com"))
    {
        // 取消WebView内的导航
        e.Cancel = true;
        // 在默认浏览器打开链接
        Launcher.TryOpenAsync(e.Url);
    }
}

MainPage.xaml

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ProteoApp.MainPage"
             NavigationPage.HasNavigationBar="False">
    <Grid>
        <WebView 
                 x:Name="proteoWebView"
                 Source="https://mywebsite.com"
                 Grid.Row="0"
                 Grid.Column="0"
                 VerticalOptions="FillAndExpand"
                 HorizontalOptions="FillAndExpand"/>
    </Grid>
</ContentPage>

开发环境

  • Visual Studio 2022
  • .NET 7.0
  • 问题出现于Pixel 5 – API 33(Android 13.0)模拟器

解决方案

针对Android平台,target="_blank"的链接默认不会触发WebView的Navigating事件,需要通过自定义WebView渲染器拦截新窗口请求:

1. Android平台自定义渲染器

在Android项目中创建以下类:

using Android.Webkit;
using Microsoft.Maui.Controls.Compatibility.Platform.Android;
using Microsoft.Maui.Controls.Platform;

[assembly: ExportRenderer(typeof(WebView), typeof(CustomWebViewRenderer))]
namespace ProteoApp.Platforms.Android
{
    public class CustomWebViewRenderer : WebViewRenderer
    {
        public CustomWebViewRenderer(Context context) : base(context) { }

        protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
        {
            base.OnElementChanged(e);

            if (Control != null)
            {
                Control.SetWebViewClient(new CustomWebViewClient());
                Control.SetWebChromeClient(new CustomWebChromeClient());
            }
        }
    }

    public class CustomWebViewClient : WebViewClient
    {
        public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, IWebResourceRequest request)
        {
            var url = request.Url.ToString();
            if (!url.StartsWith("https://mywebsite.com"))
            {
                _ = Launcher.TryOpenAsync(url);
                return true;
            }
            return base.ShouldOverrideUrlLoading(view, request);
        }
    }

    public class CustomWebChromeClient : WebChromeClient
    {
        public override bool OnCreateWindow(Android.Webkit.WebView view, bool isDialog, bool isUserGesture, Message resultMsg)
        {
            var newWebView = new Android.Webkit.WebView(view.Context);
            newWebView.SetWebViewClient(new CustomWebViewClient());
            var transport = (WebView.WebViewTransport)resultMsg.Obj;
            transport.WebView = newWebView;
            resultMsg.SendToTarget();
            return true;
        }
    }
}

2. 确认Android权限

确保AndroidManifest.xml中已添加互联网权限:

<uses-permission android:name="android.permission.INTERNET" />

3. (可选)iOS平台适配

如果需要支持iOS,创建iOS自定义渲染器:

using WebKit;
using Microsoft.Maui.Controls.Compatibility.Platform.iOS;
using Microsoft.Maui.Controls.Platform;

[assembly: ExportRenderer(typeof(WebView), typeof(CustomWebViewRenderer))]
namespace ProteoApp.Platforms.iOS
{
    public class CustomWebViewRenderer : WebViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
        {
            base.OnElementChanged(e);

            if (Control != null)
            {
                var webView = Control as WKWebView;
                webView.Configuration.Preferences.JavaScriptEnabled = true;
                webView.NavigationDelegate = new CustomNavigationDelegate();
            }
        }
    }

    public class CustomNavigationDelegate : WKNavigationDelegate
    {
        public override void DecidePolicy(WKWebView webView, WKNavigationAction navigationAction, Action<WKNavigationActionPolicy> decisionHandler)
        {
            var url = navigationAction.Request.Url.ToString();
            if (!url.StartsWith("https://mywebsite.com"))
            {
                _ = Launcher.TryOpenAsync(url);
                decisionHandler(WKNavigationActionPolicy.Cancel);
                return;
            }
            decisionHandler(WKNavigationActionPolicy.Allow);
        }
    }
}

逻辑说明

  • Android端:OnCreateWindow处理target="_blank"的新窗口请求,通过临时WebView绑定自定义WebViewClient拦截链接;ShouldOverrideUrlLoading拦截所有导航请求,判断外部链接后跳转至默认浏览器。
  • iOS端:通过WKNavigationDelegate的DecidePolicy方法拦截导航请求,实现相同的外部链接跳转逻辑。

内容的提问来源于stack exchange,提问作者Antelion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 12:42:29