Reputation: 25
I am trying to load images in a collection view in .NET MAUI but they are not showing. The images have to be retrieved via URL or from disk, depending if they have been downloaded already. I am trying to update the image path after the ForecastData object is created in the QueryApi method. The collectionview loads the text information fine but not the images. Under every weather description there should be a small 100x100 icon for the weather.
This approach works for page in my application when a single weather object is used but I cannot seem to get it to work in a collection view. An obvious workaround is to include the images at compile time but I would prefer to fetch the icons at runtime
Page
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="WeatherApp.Pages.ForecastWeatherPage"
Title="5-Day Forecast">
<VerticalStackLayout Margin="20"
Spacing="40">
<Entry Placeholder="ZIP"
Text="{Binding ZipCode}"
MaxLength="5"
WidthRequest="200"
HeightRequest="40"
HorizontalOptions="Center"
VerticalOptions="Center"
ClearButtonVisibility="WhileEditing" />
<Label x:Name="CityLabel"
FontSize="40"
HorizontalOptions="Center"
TextColor="Gray"
Text="{Binding CityName}" />
<CollectionView ItemsSource="{Binding WeatherForecast}"
ItemsLayout="HorizontalList"
HorizontalScrollBarVisibility="Always">
<CollectionView.ItemTemplate>
<DataTemplate>
<VerticalStackLayout Margin="20"
Spacing="40">
<Label x:Name="WeatherDescriptionLabel"
FontSize="Medium"
HorizontalOptions="Center"
TextColor="SlateGray"
Text="{Binding WeatherDescription}" />
<Image Source="{Binding WeatherImagePath}"
Aspect="AspectFit"
MaximumHeightRequest="100"
MaximumWidthRequest="100" />
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</ContentPage>
view model
using WeatherApp.Services;
using WeatherApp.Models.ForecastWeatherModel;
using ForecastData = WeatherApp.Models.WeatherDataObject;
using System.Collections.ObjectModel;
using WeatherApp.Pages;
namespace WeatherApp.ViewModels
{
public class ForecastWeatherViewModel : BaseViewModel
{
private string zipCode;
private string cityName;
private Root weatherForecastRoot;
public ObservableCollection<ForecastData> WeatherForecast { get; private set; } = new ObservableCollection<ForecastData>();
public ForecastWeatherViewModel()
{
weatherForecastRoot = new Root();
zipCode = string.Empty;
cityName = "Please Enter Zip Code";
}
public string ZipCode
{
get => zipCode;
set
{
SetProperty(ref zipCode, value);
if (zipCode.Length == 5)
{
QueryApi();
}
}
}
public string CityName
{
get => cityName;
set
{
SetProperty(ref cityName, value);
}
}
private async void QueryApi()
{
if (int.TryParse(zipCode, out var convertedZipCode))
{
weatherForecastRoot = await ApiService.GetWeatherForecast(convertedZipCode);
if (weatherForecastRoot != null)
{
CityName = weatherForecastRoot.city.name;
List<ForecastData> preparationList = new List<ForecastData>();
foreach(var weatherReport in weatherForecastRoot.list)
{
foreach(var report in weatherReport.weather)
{
ForecastData weatherDataObject = new ForecastData(report.description, report.icon);
if (!FileService.isIconDownloaded(weatherDataObject.WeatherIcon))
{
byte[] imageByteArray = await ApiService.GetWeatherImageFromIconCode(weatherDataObject.WeatherIcon);
weatherDataObject.WeatherImagePath = FileService.SaveIconToAppData(imageByteArray, weatherDataObject.WeatherIcon);
}
else
{
weatherDataObject.WeatherImagePath = FileService.GetIconPath(weatherDataObject.WeatherIcon);
}
preparationList.Add(weatherDataObject);
}
}
WeatherForecast = new ObservableCollection<ForecastData>(preparationList);
OnPropertyChanged(nameof(WeatherForecast));
}
else
{
CityName = "Cannot locate city/region by zip code";
}
}
}
}
}
Upvotes: 0
Views: 1221
Reputation: 25
Setting HeightRequest="400" in the collection view revealed the icons. Lesson Learned.
<CollectionView ItemsSource="{Binding WeatherForecast}"
ItemsLayout="HorizontalList"
HorizontalScrollBarVisibility="Always"
HeightRequest="400">
<CollectionView.ItemTemplate>
<DataTemplate>
<VerticalStackLayout Margin="20"
Spacing="40">
<Label x:Name="WeatherDescriptionLabel"
FontSize="Medium"
HorizontalOptions="Center"
TextColor="SlateGray"
Text="{Binding WeatherDescription}" />
<Image Source="{Binding WeatherImagePath}"
Aspect="AspectFit"
MaximumHeightRequest="200"
MaximumWidthRequest="200" />
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Upvotes: 0
Reputation: 3917
First: It is not a correct path.
I am 99.99% sure that for icon you have something like this: "01d"
Instead of something like:http://openweathermap.org/img/wn/[email protected]
Second: This is not going to render in release at all.
At this line: <DataTemplate>
you HAVE TO specify the type you are using.
Third: (this is only recommended) I would have used Width/HeightRequest.
Upvotes: 0