将Xamarin自定义ViewCell渲染器迁移至MAUI遇绑定显示异常
问题:MAUI自定义ViewCell Handler导致绑定文本不显示
在Xamarin.Forms中通过自定义渲染器实现了ListView选中项背景色自定义,迁移到MAUI后,使用自定义Handler实现相同功能时,单元格不再显示绑定的LabelText,而是显示namespace.CustomViewCell;移除MauiProgram中的Handler配置后,文本显示恢复正常,但无法自定义选中项背景色。
相关代码
XAML代码
<ListView x:Name="ListViewMenu" HasUnevenRows="True" HorizontalOptions="Start"> <ListView.ItemTemplate> <DataTemplate> <custom:CustomViewCell SelectedItemBackgroundColor="#00552E"> <ViewCell.View> <Grid Padding="10"> <Label Text="{Binding LabelText}" FontSize="20" /> </Grid> </ViewCell.View> </custom:CustomViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView>
Xamarin自定义渲染器代码
using Foundation; using MyApp; using MyApp.iOS; using System; using System.Collections.Generic; using System.Linq; using System.Text; using UIKit; using Xamarin.Forms; using Xamarin.Forms.Platform.iOS; ///Custom Renderer for the ListView on iOS [assembly: ExportRenderer(typeof(CustomViewCell), typeof(CustomViewCellRenderer))] namespace MyApp.iOS { public class CustomViewCellRenderer : ViewCellRenderer { public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv) { var cell = base.GetCell(item, reusableCell, tv); var view = item as CustomViewCell; cell.SelectedBackgroundView = new UIView { BackgroundColor = view.SelectedItemBackgroundColor.ToUIColor(), }; return cell; } } }
MAUI相关代码
ListView.ItemsSource
new ObservableCollection<NavMenuItem> { new NavMenuItem {Id = MenuItemType.Welcome, LabelText="Home" }, new NavMenuItem {Id = MenuItemType.Bonus, LabelText="Bonus" }, new NavMenuItem {Id = MenuItemType.FourO1k, LabelText="401k" }, new NavMenuItem {Id = MenuItemType.CallSheet, LabelText="Call Sheet" } };
NavMenuItem
public class NavMenuItem { public MenuItemType Id { get; set; } public string LabelText { get; set; } } public enum MenuItemType { // 枚举成员 }
CustomViewCell
using Microsoft.Maui.Controls; public class CustomViewCell : ViewCell { public static readonly BindableProperty SelectedItemBackgroundColorProperty = BindableProperty.Create("SelectedItemBackgroundColor", typeof(Color), typeof(CustomViewCell), Color.FromRgb(0, 86, 47)); public Color SelectedItemBackgroundColor { get => (Color)GetValue(SelectedItemBackgroundColorProperty); set => SetValue(SelectedItemBackgroundColorProperty, value); } }
iOS Handler(原错误版本)
using Microsoft.Maui.Controls.Handlers.Compatibility; partial class CustomViewCellHandler : CellRenderer { public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv) { var cell = base.GetCell(item, reusableCell, tv); cell.SelectedBackgroundView = new UIView() { BackgroundColor = UIColor.FromRGB(((CustomViewCell)item).SelectedItemBackgroundColor.Red, ((CustomViewCell)item).SelectedItemBackgroundColor.Green, ((CustomViewCell)item).SelectedItemBackgroundColor.Blue), }; return cell; } }
MauiProgram.cs
public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .UseMauiCompatibility() .ConfigureMauiHandlers(h => { #if IOS h.AddHandler(typeof(CustomViewCell), typeof(namespace.Platforms.iOS.Handlers.CustomViewCellHandler)); #endif }) .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); }); return builder.Build(); }
解决方案
1. 修正iOS Handler的继承与实现
原Handler继承了CellRenderer,无法正确处理ViewCell内部视图的渲染,需改为继承ViewCellRenderer,并添加类型安全判断:
using Microsoft.Maui.Controls.Handlers.Compatibility; using UIKit; using Microsoft.Maui.Controls; namespace YourNamespace.Platforms.iOS.Handlers { public class CustomViewCellHandler : ViewCellRenderer { public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv) { var cell = base.GetCell(item, reusableCell, tv); if (item is CustomViewCell customCell) { var selectedColor = customCell.SelectedItemBackgroundColor; cell.SelectedBackgroundView = new UIView { BackgroundColor = UIColor.FromRGB( (float)selectedColor.Red, (float)selectedColor.Green, (float)selectedColor.Blue) }; } return cell; } } }
2. 修正MauiProgram中的Handler注册
确保命名空间与Handler的实际命名空间一致:
public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .UseMauiCompatibility() .ConfigureMauiHandlers(h => { #if IOS h.AddHandler(typeof(CustomViewCell), typeof(YourNamespace.Platforms.iOS.Handlers.CustomViewCellHandler)); #endif }) .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); }); return builder.Build(); }
3. 优化CustomViewCell的BindableProperty定义
使用nameof关键字提升代码可维护性:
using Microsoft.Maui.Controls; public class CustomViewCell : ViewCell { public static readonly BindableProperty SelectedItemBackgroundColorProperty = BindableProperty.Create(nameof(SelectedItemBackgroundColor), typeof(Color), typeof(CustomViewCell), Color.FromRgb(0, 86, 47)); public Color SelectedItemBackgroundColor { get => (Color)GetValue(SelectedItemBackgroundColorProperty); set => SetValue(SelectedItemBackgroundColorProperty, value); } }
原因分析
CellRenderer是所有单元格渲染器的基类,它不会自动解析ViewCell内部的View结构,因此会默认显示单元格对象的ToString()结果(即namespace.CustomViewCell)。而ViewCellRenderer是MAUI为ViewCell专门提供的兼容性渲染器基类,它会正确处理ViewCell的子视图渲染逻辑,同时允许我们扩展自定义的选中背景色功能。
内容的提问来源于stack exchange,提问作者Ryan Wilson
相关产品推荐
相关产品推荐

