Асинхронная загрузка Bitmap в Carousel

Я столкнулся с проблемой того, что я не могу понять, как загружать Bitmap асинхронно в Carousel в Avalonia. Если я правильно понял, то для этого нужно использовать ObservableCollection<> и в XAML использовать {Binding ...^} для того, чтобы указать на асинхронность выполнения.

Если для простого Image можно использовать Task<Bitmap> и все прекрасно работает, то Carousel представляет собой ItemControl и в него надо сувать коллекцию, но если я так делаю (вне зависимости от того простой это Bitmap или Task<Bitmap>), то компилятор выдает исключение (NRE).

Это абстрактный пример класса

private ObservableCollection<Task<Bitmap?>> _gallery;
private Task<Bitmap?> _poster;

var poster = Utility.LoadFromWeb("https://place.abh.ai/s3fs-public/placeholder/DSC_0089_400x400.JPG");;

Poster = poster;
Gallery = [poster, poster, poster];

А в XAML это выглядит как-то так

<Image ... Source="{Binding Poster^}"/>
<Carousel ... ItemsSource="{Binding Gallery^}"/>

Загрузчик фото выглядит стандартно (из примера документации)

using var httpClient = new HttpClient();

try
{
    var response = await httpClient.GetAsync(url);
    response.EnsureSuccessStatusCode();
    var data = await response.Content.ReadAsByteArrayAsync();
    return new Bitmap(new MemoryStream(data));
}
catch (HttpRequestException ex)
{
    Console.WriteLine($"An error occurred while downloading image '{url}' : {ex.Message}");
    return null;
}

Ответы (1 шт):

Автор решения: d1rknwh1te3

Всё оказалось проще, чем я думал. В частности, мои ошибки:

  1. Я помещал в коллекцию не Image, а Bitmap (может, можно и Bitmap, я не проверял, потом отредактирую).
  2. Мой парсер возвращал не прямую ссылку на фото, поэтому MemoryStream выдавал исключение (я думал это из-за асинхронности).
  3. Для тега Image нужно ставить ^ для асинхронности, для Carousel в этом нет необходимости, потому что ObservableCollection и без этого справляется.

Пример для потомков (Avalonia + ReactiveUI):

Свойства, где хранится наша галерея:

private ObvservableCollection<Image> _gallery = [];
public ObservableCollection<Image> Gallery
{
    get => _gallery;
    set => this.RaiseAndSetIfChanged(ref _gallery, value);
}

Последовательная загрузка:

var links = new List<string>() { "ссылка", "ссылка" };

foreach (var link in links)
{
    var image = new Image
    {
        Source = await Utility.LoadFromWeb(link)
    };

    Gallery.Add(image);
}    

Паралелльная загрузка:

var links = new List<string>() { "ссылка", "ссылка" };
var tasks = links.Select(async link => new Image { Source = await Utility.LoadFromWeb(link) });
var images = await Task.WhenAll(tasks);

Gallery = new ObservableCollection<Image>(images);

И все работает, код для загрузки изображения доступен выше.

→ Ссылка