[FIXED] Xamarin – Show image from base64 string

Issue

I’m pretty new to Xamarin and XAML stuff and here is what I’ve done so far in my portable project used by Android & iPhone (only using Android):

Item.cs (loaded from JSON)

    [JsonProperty("image")]
    private string ImageBase64 { get; set; }

    [JsonIgnore]
    private Xamarin.Forms.Image _image = null;

    [JsonIgnore]
    public Xamarin.Forms.Image Image
    {
        get
        {
            if (_image == null)
            {
                _image = new Xamarin.Forms.Image()
                {
                    Source = Xamarin.Forms.ImageSource.FromStream(() => new MemoryStream(Convert.FromBase64String(ImageBase64))),
                    BackgroundColor = Color.White,
                    WidthRequest = 64,
                    HeightRequest = 64,
                };
                OnPropertyChanged("Image");
            }
            return _image;
        }
        private set
        { _image = value; }
    }

ItemsView.xaml:

<StackLayout VerticalOptions="FillAndExpand" Padding="5,20,5,0" >
  <Label Text="Items" VerticalOptions="Center" Font="35" HorizontalOptions="Center" />
  <ListView x:Name="list" ItemsSource="{Binding Items}">
    <ListView.ItemTemplate>
      <DataTemplate>
        <ImageCell
                        Text="{Binding ItemName}"
                        Detail="{Binding Infos, StringFormat='{0}'}"
          Image.Source="{Binding Path=Image}">
        </ImageCell>
      </DataTemplate>
    </ListView.ItemTemplate>
  </ListView>
</StackLayout>

I correctly get my labels displayed but the image isn’t.
Can someone explain me what I’m doing wrong?

Solution

The type of your Image property should be ImageSource, not Image, as you apparently want to bind an ImageCell’s ImageSource property. Besides that, calling OnPropertyChanged in a property getter never works, because the PropertyChanged event has to be fired before a binding (or any other consumer) can get a changed property value.

Instead of Image.Source="{Binding ...}, the correct binding would have to be

<ImageCell ... ImageSource="{Binding Path=Image}" />

The properties should be declared like this:

private string imageBase64;
public string ImageBase64
{
    get { return imageBase64; }
    set
    {
        imageBase64 = value;
        OnPropertyChanged("ImageBase64");

        Image = Xamarin.Forms.ImageSource.FromStream(
            () => new MemoryStream(Convert.FromBase64String(imageBase64)));
    } 
}

private Xamarin.Forms.ImageSource image;
public Xamarin.Forms.ImageSource Image
{
    get { return image; }
    set
    {
        image = value;
        OnPropertyChanged("Image");
    }
}

If you really need lazy creation of the Image property value, you could make it read-only, and make the corresponding OnPropertyChanged call in the ImageBase64 setter:

private string imageBase64
public string ImageBase64
{
    get { return imageBase64; }
    set
    {
        imageBase64 = value;
        OnPropertyChanged("ImageBase64");
        OnPropertyChanged("Image");
    } 
}

private Xamarin.Forms.ImageSource image;
public Xamarin.Forms.ImageSource Image
{
    get
    {
        if (image == null)
        {
            image = Xamarin.Forms.ImageSource.FromStream(
                () => new MemoryStream(Convert.FromBase64String(ImageBase64)));
        }
        return image;
    }
}

Answered By – Clemens

Answer Checked By – David Goodson (Easybugfix Volunteer)

Leave a Reply

(*) Required, Your email will not be published