-1

I need to share an image across different pages of a Xamarin.Forms app.

I am unable to reuse both the ImageSource and stream after loading an image on a page. Hence, I need to load the same image on other pages as well.

I have posted a related issue here.

Here's some code:

public PhotoCapturedViewModel(IScreen screen, Stream stream) : base(screen, "")
{
    Photo = ImageSource.FromStream(() => stream); // This stream was already used on another page
    Apply = new DelegateCommand(_ => Publish(APPLY_PHOTO, new RenderedPhoto(stream, Description)));
}
Community
  • 1
  • 1
Scott Nimrod
  • 11,206
  • 11
  • 54
  • 118
  • Can you change `Stream stream` to `MemoryStream stream` in the function declaration? – Scott Chamberlain Feb 24 '16 at 20:06
  • I tried that. I also tried converting the used stream into bytes and then creating a new stream with the bytes from the consumed stream. That didn't work either. – Scott Nimrod Feb 24 '16 at 20:09
  • 1
    How "did it not work"? Please show your memory stream attempt and explain how it did not work, considering your question is specifically asking about how to do it with a memory stream I feel it is very relevent. – Scott Chamberlain Feb 24 '16 at 20:14
  • Or why not write the stream to file, and just pass the file path? – Jason Feb 24 '16 at 20:37

2 Answers2

1

I resolved my issue by immediately converting a recently created stream into a byte array.

I then generate new memory streams by passing the byte array around.

Creation:

var file = await service.TakePhotoAsync(mediaOptions);
var stream = file.GetStream();

using (var memoryStream = new MemoryStream())
{
    stream.CopyTo(memoryStream);
    var image = memoryStream.ToArray();
    Publish(PHOTO_CAPTURED, new ImageCaptureNavigationArgs(image));
}

Navigation:

static void OnPhotoCaptured(object obj)
{
    var args = obj as ImageCaptureNavigationArgs;
    var screen = IOCServiceRegistration<IUnityContainer>.Container.Resolve(typeof(IScreen)) as IScreen; // ReactiveUI dependency kludge. Sigh...
    screen.Router.Navigate.Execute(new PhotoCapturedViewModel(screen, args.Stream));
}

Usage:

public partial class PhotoCapturedViewModel : BaseViewModel
{
    public PhotoCapturedViewModel(IScreen screen, byte[] image) : base(screen, "")
    {
        var memoryStream = new MemoryStream(image);
        Photo = ImageSource.FromStream(() => memoryStream);
        Apply = new DelegateCommand(_ => Publish(APPLY_PHOTO, new RenderedPhoto(image, Description)));
    }
Scott Nimrod
  • 11,206
  • 11
  • 54
  • 118
0

The way I solved this is not by using the same stream, but simply setting the new images source to the source of the original image.

Try something like this:

public PhotoCapturedViewModel(IScreen screen, Image originalImage) :     base(screen, "")
{
    Photo = new Image() {Source = originalImage.Source};
}
StarterPack
  • 498
  • 1
  • 7
  • 28