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

Xamarin.Forms:通过类型转换器传递枚举参数至URL失败问题排查

Xamarin.Forms Shell跳转传递枚举类型QueryProperty报错解决方法

问题场景与错误信息

页面定义了枚举类型的绑定属性,通过Shell的GoToAsync传递参数时,抛出InvalidCastException异常,提示无法将System.String转换为自定义枚举类型。

页面代码:

[QueryProperty(nameof(EnumProp), nameof(EnumProp))]
public partial class MyPage : ContentPage
{
    public static readonly BindableProperty EnumPropProperty =
       BindableProperty.Create(nameof(EnumProp), typeof(MyEnum), typeof(MyPage), propertyChanged: OnEnumPropChanged);

    public MyEnum EnumProp
    {
        get => (MyEnum)GetValue(EnumPropProperty);
        set => SetValue(EnumPropProperty, value);
    }
}

跳转代码:

MyEnum enumProp = MyEnum.ThisValue;
string dest = $"{nameof(MyPage)}?{nameof(MyPage.EnumProp)}={enumProp}";
await Shell.Current.GoToAsync(dest);

错误堆栈:

System.InvalidCastException
  HResult=0x80004002
  Nachricht = Invalid cast from 'System.String' to 'XXX.MyEnum'.
  Quelle = System.Private.CoreLib
  Stapelüberwachung:
   bei System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
   bei Xamarin.Forms.ShellContent.ApplyQueryAttributes(Object content, IDictionary`2 query, IDictionary`2 oldQuery)
   bei Xamarin.Forms.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes)
   bei Xamarin.Forms.BindableObject.SetValue(BindableProperty property, Object value, Boolean fromStyle, Boolean checkAccess)
   bei Xamarin.Forms.ShellNavigationManager.ApplyQueryAttributes(Element element, IDictionary`2 query, Boolean isLastItem, Boolean isPopping)
   bei Xamarin.Forms.ShellSection.<GoToAsync>d__69.MoveNext()
   bei Xamarin.Forms.ShellNavigationManager.<GoToAsync>d__13.MoveNext()
   bei XXX.MyPage.<ToDetail>d__17.MoveNext() in C:\Users\MyUser\Development\...\PackObjectItem.cs: Zeile46

此前给EnumProp属性添加TypeConverter特性未生效,原因是Shell处理QueryProperty时直接操作BindableProperty,而非属性的setter方法。

解决方案

方案一:给BindableProperty指定TypeConverter

修改BindableProperty的定义,在创建时直接指定typeConverter参数,同时实现对应的枚举转换类:

  1. 定义通用枚举转换器:
public class StringToEnumConverter<T> : TypeConverter where T : Enum
{
    public override object ConvertFromInvariantString(string value)
    {
        if (string.IsNullOrWhiteSpace(value))
            return default(T);
        
        return Enum.TryParse(typeof(T), value, ignoreCase: true, out var result) 
            ? result 
            : default(T);
    }
}
  1. 修改BindableProperty定义:
public static readonly BindableProperty EnumPropProperty =
    BindableProperty.Create(
        nameof(EnumProp), 
        typeof(MyEnum), 
        typeof(MyPage), 
        propertyChanged: OnEnumPropChanged,
        typeConverter: typeof(StringToEnumConverter<MyEnum>)
    );

方案二:通过中间字符串属性手动转换

定义一个字符串类型的中间属性接收Query参数,在其setter中手动将字符串转换为枚举类型:

[QueryProperty(nameof(EnumPropString), nameof(EnumProp))]
public partial class MyPage : ContentPage
{
    public static readonly BindableProperty EnumPropProperty =
       BindableProperty.Create(nameof(EnumProp), typeof(MyEnum), typeof(MyPage), propertyChanged: OnEnumPropChanged);

    public MyEnum EnumProp
    {
        get => (MyEnum)GetValue(EnumPropProperty);
        set => SetValue(EnumPropProperty, value);
    }

    // 中间属性,接收Query传递的字符串
    public string EnumPropString
    {
        set
        {
            if (Enum.TryParse<MyEnum>(value, ignoreCase: true, out var enumValue))
            {
                EnumProp = enumValue;
            }
            // 可添加无效值的默认处理逻辑
        }
    }
}

此方案无需额外实现转换器,通过手动转换避免类型异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 19:45:20