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

MAUI中使用SkiaSharp基于ContentView自定义组件报错的问题咨询

MAUI自定义组件实现疑问解答

核心结论

  • 创建MAUI自定义组件不需要强制创建类库或添加注册方法,这只是自定义渲染组件的一种实现方式,并非唯一要求。
  • 完全可以继续沿用Xamarin Forms的思路,以ContentView为基类,内部嵌套SKCanvasView来实现环形图组件。

迁移后崩溃的原因及修复方案

你迁移后出现Microsoft.UI.Xaml.Controls.Frame.NavigationFailed崩溃,大概率是MAUI中SKCanvasView的初始化、生命周期逻辑和Xamarin Forms存在差异,而非基类选择的问题。可以按以下步骤排查修复:

  1. 确认SkiaSharp MAUI包的配置
    确保项目已安装SkiaSharp.Views.Maui和SkiaSharp.Views.Maui.Controls NuGet包,并且在MauiProgram.cs中完成初始化:

    builder.UseSkiaSharp();
    
  2. 调整SKCanvasView的事件绑定时机
    避免在构造函数中直接绑定PaintSurface事件,改用ContentView的OnParentSet生命周期方法处理,确保控件完成MAUI的初始化流程:

    public class Doughnut : ContentView
    {
        private SKCanvasView _canvasView;
    
        public Doughnut()
        {
            _canvasView = new SKCanvasView();
            Content = _canvasView;
        }
    
        protected override void OnParentSet()
        {
            base.OnParentSet();
            if (Parent != null)
            {
                // 先解绑再绑定,避免重复订阅
                _canvasView.PaintSurface -= OnCanvasViewPaintSurface;
                _canvasView.PaintSurface += OnCanvasViewPaintSurface;
            }
            else
            {
                _canvasView.PaintSurface -= OnCanvasViewPaintSurface;
            }
        }
    
        private void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
        {
            // 保留原有的环形图绘制逻辑
        }
    }
    
  3. 确保可绑定属性触发重绘
    MAUI中可绑定属性的注册逻辑和Xamarin Forms基本一致,但要在属性变更时主动触发画布重绘:

    public static readonly BindableProperty ProgressProperty =
        BindableProperty.Create(nameof(Progress), typeof(double), typeof(Doughnut), 0.0,
            propertyChanged: (bindable, oldVal, newVal) =>
            {
                if (bindable is Doughnut doughnut)
                {
                    doughnut._canvasView.InvalidateSurface();
                }
            });
    
    public double Progress
    {
        get => (double)GetValue(ProgressProperty);
        set => SetValue(ProgressProperty, value);
    }
    

两种实现方式的差异

  • 继承SKCanvasView+注册Handler:这属于自定义原生渲染组件,适合需要直接控制原生平台渲染逻辑的场景。注册Handler是为了让MAUI的处理系统识别自定义组件并关联对应的渲染器,但这种方式并非必须,只有当你需要替换或扩展原生渲染逻辑时才需要使用。
  • ContentView嵌套SKCanvasView:这属于组合式组件,和Xamarin Forms的实现思路完全一致,利用MAUI内置控件组合实现功能,无需额外注册,更适合快速迁移现有Xamarin组件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 04:40:57