MAUI中使用SkiaSharp基于ContentView自定义组件报错的问题咨询
MAUI自定义组件实现疑问解答
核心结论
- 创建MAUI自定义组件不需要强制创建类库或添加注册方法,这只是自定义渲染组件的一种实现方式,并非唯一要求。
- 完全可以继续沿用Xamarin Forms的思路,以
ContentView为基类,内部嵌套SKCanvasView来实现环形图组件。
迁移后崩溃的原因及修复方案
你迁移后出现Microsoft.UI.Xaml.Controls.Frame.NavigationFailed崩溃,大概率是MAUI中SKCanvasView的初始化、生命周期逻辑和Xamarin Forms存在差异,而非基类选择的问题。可以按以下步骤排查修复:
确认SkiaSharp MAUI包的配置
确保项目已安装SkiaSharp.Views.Maui和SkiaSharp.Views.Maui.ControlsNuGet包,并且在MauiProgram.cs中完成初始化:builder.UseSkiaSharp();调整
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) { // 保留原有的环形图绘制逻辑 } }确保可绑定属性触发重绘
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
相关产品推荐
相关产品推荐

