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

Shell导航传递ImageSource参数报错:如何单独传递该对象?

问题:Shell导航单独传递ImageSource对象时抛出InvalidCastException异常

尝试通过Shell导航将ImageSource对象单独传递到另一页面时,执行以下代码:

await Shell.Current.GoToAsync($"{nameof(FullScreenImagePage)}?",
new Dictionary<string, object>
{
    ["TempImageSource"] = TempPhotoPoint.ExamplePicture
});

抛出异常:

System.InvalidCastException: 'Object must implement IConvertible.'

其中ExamplePicture为ImageSource类型,FullScreenImagePage的ViewModel配置如下:

[QueryProperty(nameof(TempImageSource), nameof(TempImageSource))]
[ObservableProperty] ImageSource tempImageSource;

ViewModel已通过BindingContext与页面关联,传递包含ImageSource的TempPhotoPoint对象时一切正常,询问如何单独传递ImageSource对象。


原因分析

Shell导航的查询参数机制默认要求传递的对象实现IConvertible接口,而ImageSource并未实现该接口,直接传递会触发类型转换异常;但传递包含ImageSource的完整对象时,Shell会将其作为导航参数的整体对象传递,绕过了IConvertible的校验逻辑,因此可以正常工作。

解决方法

方案1:使用NavigationParameters传递复杂对象

利用Shell的NavigationParameters传递复杂对象,无需实现IConvertible:

  1. 修改导航代码:
var parameters = new NavigationParameters();
parameters.Add("TempImageSource", TempPhotoPoint.ExamplePicture);
await Shell.Current.GoToAsync(nameof(FullScreenImagePage), parameters);
  1. 在ViewModel中实现INavigatedAware接口接收参数:
public class FullScreenImageViewModel : INavigatedAware
{
    [ObservableProperty]
    ImageSource tempImageSource;

    public void OnNavigatedTo(NavigatedToEventArgs args)
    {
        if (args.Parameter is NavigationParameters navParams && 
            navParams.ContainsKey("TempImageSource"))
        {
            TempImageSource = navParams["TempImageSource"] as ImageSource;
        }
    }

    public void OnNavigatedFrom(NavigatedFromEventArgs args)
    {
        // 可选实现导航离开时的逻辑
    }
}

方案2:将ImageSource转换为可序列化的字符串传递

如果必须使用查询参数,可根据ImageSource的具体类型(如UriImageSource或FileImageSource)转换为字符串传递,再在目标页面重构:

  1. 导航代码:
string imageParam = string.Empty;
if (TempPhotoPoint.ExamplePicture is UriImageSource uriSource)
{
    imageParam = uriSource.Uri.AbsoluteUri;
}
else if (TempPhotoPoint.ExamplePicture is FileImageSource fileSource)
{
    imageParam = fileSource.File;
}

await Shell.Current.GoToAsync($"{nameof(FullScreenImagePage)}?TempImageSource={imageParam}");
  1. ViewModel中处理字符串参数并重构ImageSource:
[QueryProperty(nameof(TempImageSourceString), "TempImageSource")]
public partial class FullScreenImageViewModel : ObservableObject
{
    [ObservableProperty]
    string tempImageSourceString;

    [ObservableProperty]
    ImageSource tempImageSource;

    partial void OnTempImageSourceStringChanged(string value)
    {
        if (string.IsNullOrEmpty(value)) return;
        
        if (Uri.TryCreate(value, UriKind.Absolute, out var uri))
        {
            TempImageSource = ImageSource.FromUri(uri);
        }
        else
        {
            TempImageSource = ImageSource.FromFile(value);
        }
    }
}

方案3:将ImageSource包装到简单对象中传递

模仿之前传递TempPhotoPoint的方式,把ImageSource包装到一个仅包含该属性的类中:

  1. 定义包装类:
public class ImageSourceWrapper
{
    public ImageSource Source { get; set; }
}
  1. 修改导航代码:
await Shell.Current.GoToAsync(nameof(FullScreenImagePage), 
    new Dictionary<string, object>
    {
        ["ImageWrapper"] = new ImageSourceWrapper { Source = TempPhotoPoint.ExamplePicture }
    });
  1. ViewModel接收并提取ImageSource:
[QueryProperty(nameof(ImageWrapper), "ImageWrapper")]
public partial class FullScreenImageViewModel : ObservableObject
{
    [ObservableProperty]
    ImageSourceWrapper imageWrapper;

    [ObservableProperty]
    ImageSource tempImageSource;

    partial void OnImageWrapperChanged(ImageSourceWrapper value)
    {
        TempImageSource = value?.Source;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 20:52:43