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

将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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 08:36:03