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

Xamarin iOS分享扩展获取图片后无法绑定显示的问题求助

Xamarin.Forms 5分享扩展图片绑定显示失败问题解决

我使用Xamarin.Forms 5.X.X创建了Demo应用,并开发了分享扩展,目前能成功获取到图片的文件路径,但尝试两种方式均无法在页面绑定显示图片:

  • 通过ImageResource.FromFile绑定文件路径
  • 通过流绑定

相关代码

CustomShareViewController代码

public class CustomShareViewController: SLComposeServiceViewController
{
    public CustomShareViewController(IntPtr handle) : base(handle)
    {
    }

    public override void DidReceiveMemoryWarning()
    {
        base.DidReceiveMemoryWarning();
    }

    public override async void ViewDidLoad()
    {
         base.ViewDidLoad();

        string urlstr = string.Empty;

        NSExtensionItem item = ExtensionContext.InputItems[0];
        var itemProvider = item.Attachments[0];

        var type = itemProvider.Description.Split('"');
        if (itemProvider.HasItemConformingTo(type[1]))
        {
            var load = await itemProvider.LoadItemAsync(type[1], null);
            NSUrl newUrl = (NSUrl)load;
            urlstr = newUrl.FilePathUrl.ToString();
        }

        if (!Xamarin.Forms.Forms.IsInitialized)
            Xamarin.Forms.Forms.Init();

        var xfPage = new ShareMainPage();
        var viewModel = (ShareMainPageViewModel)xfPage.BindingContext;
        viewModel.Message = urlstr;
        viewModel.Image = urlstr;
        //viewModel.BindableImage = ImageSource.FromStream(() => new MemoryStream(byteArray));
        viewModel.DoCommand = new Command(() => DoneClicked());
        var newController = xfPage.CreateViewController();
        newController.ModalPresentationStyle = UIModalPresentationStyle.FormSheet;
        this.PresentModalViewController(newController, false);
    }

    public override bool ShouldInteractWithUrl(UITextView textView, NSUrl url, NSRange characterRange, UITextItemInteraction interaction)
    {
        return base.ShouldInteractWithUrl(textView, url, characterRange, interaction);
    }

    public override bool IsContentValid()
    {
        return true;
    }

    public override void DidSelectPost()
    {
    }

    public override void PresentationAnimationDidFinish()
    {
        base.PresentationAnimationDidFinish();
    }

    private void DoneClicked()
    {
        ExtensionContext.CompleteRequest(ExtensionContext.InputItems, null);
    }

    private void WriteToDebugFile(string dbgText)
    {
        var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        var filename = Path.Combine(documents, "Share-Extension-Debug.txt");

        if (!File.Exists(filename))
        {
            File.WriteAllText(filename, $"\n{DateTime.Now} - {dbgText}");
        }
        else
        {
            File.AppendAllText(filename, $"\n{DateTime.Now} - {dbgText}");
        }
    }
}

ShareMainPage的XAML代码

<?xml version="1.0" encoding="UTF-8" ?>
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
 xmlns:local="clr-namespace:Demo.ViewModels"
x:DataType="local:ShareMainPageViewModel"
 xmlns:converters="clr-namespace:LifeApp.Mobile.Converters"
BackgroundColor="Green"
x:Class="LifeApp.Mobile.Views.ShareMainPage">
<ContentPage.BindingContext>
    <local:ShareMainPageViewModel Message="Hello from Xamarin.Forms!" />
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
  
        <Image Source="{Binding BindableImage}"
               VerticalOptions="Start"
               HorizontalOptions="CenterAndExpand" WidthRequest="200" HeightRequest="150"/>
        <Label Text="{Binding Message}" TextColor="Black" FontSize="Medium" VerticalTextAlignment="Center"/>
        <Button Command="{Binding DoCommand}" Text="Do the jungle!" TextColor="Black" />
</StackLayout>
</ContentPage.Content>
</ContentPage>

ShareMainPageViewModel代码

using System;
using System.ComponentModel;
using System.IO;
using System.Windows.Input;
using Xamarin.Essentials;
using Xamarin.Forms;
using Xamarin.Forms.Shapes;

namespace Demo.ViewModels
{
    public class ShareMainPageViewModel : INotifyPropertyChanged
    {
    public event PropertyChangedEventHandler PropertyChanged;

    private string _message;
    public string Message
    {
        get { return _message; }
        set
        {
            if (_message != value)
            {
                _message = value;
                PropertyChanged?.Invoke(this, new 
PropertyChangedEventArgs(nameof(Message)));
            }
        }
    }

    private string _image;
    public string Image
    {
        get { return _image; }
        set
        {
            if (_image != value)
            {
                _image = value;
                PropertyChanged?.Invoke(this, new 
PropertyChangedEventArgs(nameof(Image)));
            }
        }
    }

    public ImageSource _bindableImage { get; set; }

    public ImageSource BindableImage
    {
        get
        {
            return _bindableImage;
        }
        set
        {
            if (_bindableImage !=null)
            {
            
                _bindableImage = value;

                PropertyChanged?.Invoke(this, new 
PropertyChangedEventArgs(nameof(BindableImage)));

            }
        }
    }

    private ICommand _doCommand;
    public ICommand DoCommand
    {
        get { return _doCommand; }
        set
        {
            if (_doCommand != value)
            {
                _doCommand = value;
                PropertyChanged?.Invoke(this, new 
PropertyChangedEventArgs(nameof(DoCommand)));
            }
        }
    }

    public ShareMainPageViewModel()
    {
        DoCommand = new Command(OnDoCommandExecuted);
    }

    private void OnDoCommandExecuted(object state)
    {
        Message = $"Job {Environment.TickCount} has been completed!";
    }
}
}

获取到的图片路径示例:file:///Users/xxxx/Library/Developer/CoreSimulator/Devices/58453DF3-58CF-4591-AC91-6A096FD7B814/data/Containers/Data/Application/1466F475-0F58-4F94-8511-B0BD9FE86DCA/tmp/WKFileShare-FbFp8eSD/adcf0796-2088-4d85-9420-c1d58c15cca4/....JPG


解决方法

1. 修正文件路径处理

获取到的路径是带file://前缀的URL,ImageSource.FromFile需要的是本地文件路径(不带scheme),修改CustomShareViewController中的路径处理代码:

// 替换原来的urlstr = newUrl.FilePathUrl.ToString();
urlstr = newUrl.FilePathUrl.Path;

2. 修复ViewModel的BindableImage属性setter逻辑

当前setter中判断if (_bindableImage !=null)会导致第一次赋值时不触发PropertyChanged,UI无法更新,修改为:

public ImageSource BindableImage
{
    get
    {
        return _bindableImage;
    }
    set
    {
        if (_bindableImage != value)
        {
            _bindableImage = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(BindableImage)));
        }
    }
}

3. 选择合适的绑定方式

方式一:文件路径绑定

在CustomShareViewController中给ViewModel赋值:

viewModel.BindableImage = ImageSource.FromFile(urlstr);

方式二:流绑定

读取文件字节流后赋值:

byte[] imageBytes = File.ReadAllBytes(urlstr);
viewModel.BindableImage = ImageSource.FromStream(() => new MemoryStream(imageBytes));

额外说明

iOS分享扩展默认拥有临时目录的访问权限,处理后的路径无需额外权限配置即可访问。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 03:10:43