我目前正在开发
CollectionView
以在 .NET MAUI 上显示大量图像。我没有使用任何第三方库来管理图像缓存。我能够启动一项任务,最终利用 INotifyPropertyChanged
内部模型中的 DataTemplate
来更新图像的 ImageSource
属性,并且效果非常好。但不幸的是,当我滚动 CollectionView
时,我丢失了 Grid
单元格内的图像,尽管检查了包含 ObservableCollection<T>
属性的 ImageSource
,但我可以找到 MemoryStream
,并且 它还没有被处置 其他地方。
我附上了用于检索图像和创建流的方法:
// Here's a portion of my ViewModel...
private async Task CaricaDati()
{
try
{
InFetching = true;
AllFetched = false;
files = await storageService.GetAllBlobsAsync(idCantiere, "Rapporti");
IEnumerable<AllegatoModel> pageAllegati = (await CaricaDatiSub(0, paginaAllegati)).Select(f => new AllegatoModel
{
Nome = f.Name,
ImageAspect = Utility.GetTipoFile(Path.GetExtension(f.Name)) == Enumerazioni.TipoFile.Immagine ||
Utility.GetTipoFile(Path.GetExtension(f.Name)) == Enumerazioni.TipoFile.PDF ? Aspect.Fill : Aspect.Center
});
if (pageAllegati is not null && pageAllegati.Any())
{
Allegati = new ObservableRangeCollection<AllegatoModel>(pageAllegati);
_ = Task.Run(() => DownloadImagesAsync(pageAllegati));
}
}
catch (Exception ex)
{
AppCenterEventManager.TrackError(ex, string.Empty);
UIMessagesManager.ShowMessage(Stringhe.ATTENZIONE, Stringhe.ERR_IMPREVISTO);
}
finally { InFetching = false; }
}
private async Task DownloadImagesAsync(IEnumerable<AllegatoModel> pageAllegati)
{
if (pageAllegati is not null)
{
foreach (var item in pageAllegati)
{
var memStream = await storageService.DownloadStreamAsync(idCantiere, item.Nome);
Allegati.FirstOrDefault(a => a.Nome == item.Nome).Anteprima = ImageSource.FromStream(() => memStream);
}
}
}
// This is my StorageService.cs class...
public async Task<MemoryStream> DownloadStreamAsync(string cName, string bName)
{
BlobContainerClient container = blobService.GetBlobContainerClient(cName);
BlobClient file = container.GetBlobClient(bName);
if (file.Exists())
{
MemoryStream str = new();
await file.DownloadToAsync(str);
str.Position = 0;
return str;
}
else
return null;
}
我还缺少什么策略吗?如果
Grid
仍然存在,那么 StreamImageSource
单元格怎么会变成空的?
答案是在
MemoryStream
的生命周期中,因为它需要在 CollectionView
的相同上下文中创建才能保持活动状态。
正确的使用方法如下:
private async Task DownloadImagesAsync(IEnumerable<AllegatoModel> pageAllegati)
{
if (pageAllegati is not null)
{
foreach (var item in pageAllegati)
{
MemoryStream memStream = await storageService.DownloadStreamAsync(idCantiere, item.Nome);
byte[] strArray = Utility.StreamToByteArray(memStream);
Allegati.FirstOrDefault(a => a.Nome == item.Nome).Anteprima = ImageSource.FromStream(() => new MemoryStream(strArray));
}
}
}
需要经过字节数组转换,然后再返回Stream。
这非常有效,拯救了我的一天!一种评论是,只有当 CollectionView 方向为水平时才会发生。