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

Xamarin.macOS自定义CustomWebView的Navigated事件未触发如何解决

解决方案

问题根因

你当前使用了默认的空WKNavigationDelegate实例,该实例没有实现WKWebView的导航回调方法,也没有将原生导航事件映射到自定义CustomWebView的Navigated事件上,所以事件无法触发,同时代码中存在重复赋值NavigationDelegate的无效逻辑。

实现代码

第一步:自定义WKNavigationDelegate子类

该子类负责接收原生WKWebView的导航回调,并映射到CustomWebView的对应事件:

public class CustomWebViewNavigationDelegate : WKNavigationDelegate
{
    private readonly CustomWebView _customWebView;

    public CustomWebViewNavigationDelegate(CustomWebView webView)
    {
        _customWebView = webView;
    }

    // 页面开始加载时触发,对应CustomWebView的Navigating事件
    public override void DidStartProvisionalNavigation(WKWebView webView, WKNavigation navigation)
    {
        base.DidStartProvisionalNavigation(webView, navigation);
        var args = new WebNavigatingEventArgs(WebNavigationEvent.NewPage, 
            new UrlWebViewSource { Url = webView.Url?.AbsoluteString }, 
            webView.Url?.AbsoluteString);
        _customWebView.SendNavigating(args);
    }

    // 页面加载完成时触发,对应CustomWebView的Navigated事件
    public override void DidFinishNavigation(WKWebView webView, WKNavigation navigation)
    {
        base.DidFinishNavigation(webView, navigation);
        var args = new WebNavigatedEventArgs(WebNavigationEvent.NewPage, 
            new UrlWebViewSource { Url = webView.Url?.AbsoluteString }, 
            webView.Url?.AbsoluteString, 
            WebNavigationResult.Success);
        _customWebView.SendNavigated(args);
    }

    // 页面加载失败时触发
    public override void DidFailNavigation(WKWebView webView, WKNavigation navigation, NSError error)
    {
        base.DidFailNavigation(webView, navigation, error);
        var args = new WebNavigatedEventArgs(WebNavigationEvent.NewPage, 
            new UrlWebViewSource { Url = webView.Url?.AbsoluteString }, 
            webView.Url?.AbsoluteString, 
            WebNavigationResult.Failure);
        _customWebView.SendNavigated(args);
    }

    // provisional阶段导航失败时触发
    public override void DidFailProvisionalNavigation(WKWebView webView, WKNavigation navigation, NSError error)
    {
        base.DidFailProvisionalNavigation(webView, navigation, error);
        var args = new WebNavigatedEventArgs(WebNavigationEvent.NewPage, 
            new UrlWebViewSource { Url = webView.Url?.AbsoluteString }, 
            webView.Url?.AbsoluteString, 
            WebNavigationResult.Failure);
        _customWebView.SendNavigated(args);
    }
}

第二步:修改CustomWebView类

在你的CustomWebView类中添加方法,暴露内部的事件触发逻辑:

public class CustomWebView : WebView
{
    // 保留你原来的CustomUserAgent等自定义属性

    public void SendNavigating(WebNavigatingEventArgs args)
    {
        OnNavigating(args);
    }

    public void SendNavigated(WebNavigatedEventArgs args)
    {
        OnNavigated(args);
    }
}

第三步:修改自定义Renderer代码

替换原来的空WKNavigationDelegate,删掉重复赋值逻辑:

[assembly: ExportRenderer(typeof(CustomWebView), typeof(CustomWebViewRenderer))]
namespace DesktopClient.MacOS.CustomRenderers
{
    public class CustomWebViewRenderer : ViewRenderer<CustomWebView, WKWebView>
    {
        private WKWebView wkWebView;

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

            if (Control == null)
            {
                WKWebViewConfiguration config = new WKWebViewConfiguration();                
                wkWebView = new WKWebView(Frame, config)
                {
                    // 使用自定义的NavigationDelegate
                    NavigationDelegate = new CustomWebViewNavigationDelegate(e.NewElement)
                };
                SetNativeControl(wkWebView);
                WKWebViewContainer.WKWebView = wkWebView;
            }

            if (e.NewElement != null)
            {
                if (e.NewElement.Source is UrlWebViewSource source && !string.IsNullOrEmpty(source.Url))
                {
                    Control.LoadRequest(new NSUrlRequest(new NSUrl(source.Url)));
                }
                Control.CustomUserAgent = e.NewElement.UserAgent;
            }
        }
    }
}

注意事项

  • 如果需要处理跨域请求、权限申请、跳转拦截等逻辑,可在CustomWebViewNavigationDelegate中重写对应的WKNavigationDelegate方法实现。
  • 如出现内存泄漏问题,可将Delegate中的_customWebView改为弱引用持有。
  • 若使用MAUI框架,更推荐使用Handler替代自定义Renderer实现,逻辑与上述映射思路一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 13:54:04