.NET MAUI中CollectionView滚动时图片消失问题求助
问题根源与解决策略
你遇到的问题核心在于StreamImageSource的委托只会被执行一次:当CollectionView滚动导致ViewCell被回收复用时,原来的MemoryStream已经被读取至末尾,无法再次提供有效数据,因此图片显示空白。同时直接持有MemoryStream会导致内存无法及时释放,进一步加剧问题。
1. 存储图片字节数组而非直接持有MemoryStream
将MemoryStream转换为byte[]存储在模型中,每次需要显示图片时创建新的MemoryStream,确保每次都能从流的起始位置读取数据:
修改AllegatoModel
public class AllegatoModel : INotifyPropertyChanged { private byte[] _imageBytes; public byte[] ImageBytes { get => _imageBytes; set { _imageBytes = value; OnPropertyChanged(); OnPropertyChanged(nameof(Anteprima)); } } public ImageSource Anteprima => ImageBytes != null ? ImageSource.FromStream(() => new MemoryStream(ImageBytes)) : null; // 其他原有属性... public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
更新下载逻辑
private async Task DownloadImagesAsync(IEnumerable<AllegatoModel> pageAllegati) { if (pageAllegati is null) return; foreach (var item in pageAllegati) { using var memStream = await storageService.DownloadStreamAsync(idCantiere, item.Nome); if (memStream == null) continue; // 将流转换为字节数组存储 var imageBytes = memStream.ToArray(); // 确保在UI线程更新属性 MainThread.BeginInvokeOnMainThread(() => { Allegati.FirstOrDefault(a => a.Nome == item.Nome).ImageBytes = imageBytes; }); } }
2. 优化异步调用逻辑
移除多余的Task.Run包裹,直接异步等待下载任务,避免不必要的线程切换:
// 替换原来的Task.Run调用 await DownloadImagesAsync(pageAllegati);
3. 确保Stream资源及时释放
在DownloadStreamAsync的调用处使用using语句,确保流在转换为字节数组后被及时释放,避免内存泄漏:
using var memStream = await storageService.DownloadStreamAsync(idCantiere, item.Nome);
4. 确认CollectionView复用策略
确保CollectionView使用默认的RecycleElement缓存策略(默认配置),同时检查DataTemplate中Image控件的布局设置,避免因固定尺寸或布局异常导致的显示问题:
<CollectionView CachingStrategy="RecycleElement"> <!-- DataTemplate内容 --> </CollectionView>
内容的提问来源于stack exchange,提问作者ImproveSoftware
相关产品推荐
相关产品推荐

