I need to download static images from my CDN and display them in my Xamarin.Forms view. I'm new to Xamarin specifically and I'm having a hard time figuring out how to load an image from a byte array pulled from a HTTP request.
I have the following XAML in my View:
<ListView ItemsSource="{Binding Images}">
<ListView.ItemTemplate>
<DataTemplate>
<ImageCell ImageSource="{Binding .}">
</ImageCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
In my code behind I'm fetching the image and trying to bind to a Collection of ImageSource
instances.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
public ObservableCollection<ImageSource> Images { get; set; } = new ObservableCollection<ImageSource>();
protected override async void OnAppearing()
{
base.OnAppearing();
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Referer", "https://foo.bar/");
var response = await client.GetAsync("https://foo.bar/library/5.jpg");
byte[] image = await response.Content.ReadAsByteArrayAsync();
var imageSource = ImageSource.FromStream(() => new MemoryStream(image));
this.Images.Add(imageSource);
}
}
When I do this the Image within the StackLayout is empty. I know I can instead just bind to a URL and the ImageSource can download it for me but I'm required to pass a Referrer
Header. I can't see anyway for me to force the XAML Image
view to allow custom headers, nor can I see a way to do it if I instantiate an instance of ImageSource
in my code behind.
When I read the documentation on ImageSource
it sounds like it only supports URI, File, Stream and App Resources to load images from. Since I had an array of bytes I wrapped it in a MemoryStream
and called ImageSource.FromStream
. Nothing loads when the app runs though - the ImageCell
is empty.
I know the image was downloaded. I converted the byte[]
to a Base64 string then dropped it into Base64 to Image Decoder. The image loads no problem so I know it's being downloaded properly. What I don't understand is why I can't get the image to render on a ImageSource
.
I've also tried to just use a normal Image
control and have the same problem.
<ScrollView>
<ContentView>
<StackLayout BindableLayout.ItemsSource="{Binding Images}" Orientation="Horizontal">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}"></Image>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ContentView>
</ScrollView>
Am I doing something completely wrong here or is dynamic downloading of images from the internet with special Headers something I can't do in Xamarin.Forms?
Try to add this.BindingContext = this;
in page constructor.
public MainPage()
{
InitializeComponent();
this.BindingContext = this;
}