使用MVVM模式从文件选择器填充CollectionView的问题
MVVM模式下CollectionView无法展示选中文件的问题解决
问题核心原因
你的ViewModel存在三个关键问题导致UI无法更新:
- 集合类型错误:使用
List<Item>而非ObservableCollection<Item>,List的增删操作不会触发UI绑定的属性变更通知。 - 属性通知缺失:手动定义的
Items属性没有实现INotifyPropertyChanged,即使赋值也无法通知CollectionView更新。 - 逻辑混乱:
sourceData与Items的循环赋值、sourceData = null这类操作导致数据丢失或未正确更新。
修复后的ViewModel代码
using CommunityToolkit.Mvvm.ComponentModel; using Microsoft.Maui.Storage; using System.Collections.ObjectModel; using System.IO; using System.Linq; public partial class FileViewModel : ObservableObject { // 用ObservableCollection实现自动通知,替代List [ObservableProperty] private ObservableCollection<Item> selectedFiles = new(); private readonly IFolderPicker _folderPicker; public FileViewModel(IFolderPicker folderPicker) { _folderPicker = folderPicker; } // 用async Task替代async void,避免潜在异常捕获问题 public async Task AddFileAsync() { var customFileType = new FilePickerFileType(new Dictionary<DevicePlatform, IEnumerable<string>> { // 补充你的文件类型逻辑,例如:{ DevicePlatform.WinUI, new[]{"ics"} } }); var results = await FilePicker.PickMultipleAsync(new PickOptions { FileTypes = customFileType, }); if (results == null) return; foreach (var result in results) { FileInfo fileInfo = new FileInfo(result.FullPath); double size = FileSize(fileInfo); // 用LINQ简化重复文件检查 bool fileExists = SelectedFiles.Any(item => item.FilePath.Equals(result.FullPath)); if (!fileExists) { SelectedFiles.Add(new Item { FilePath = result.FullPath, FileSize = size }); } // 文件已存在的提示逻辑可保留,需注入弹窗服务实现 } } private double FileSize(FileInfo fileInfo) { // 你的文件大小计算逻辑,示例:转换为KB return fileInfo.Length / 1024.0; } } public class Item { public string FilePath { get; set; } public double FileSize { get; set; } }
对应XAML修改
将CollectionView的ItemsSource绑定到修复后的属性:
<CollectionView Grid.ColumnSpan="2" Grid.Row="1" SelectionMode="Single" VerticalOptions="FillAndExpand" VerticalScrollBarVisibility="Always" ItemTemplate="{StaticResource appDataTemplate}" ItemsSource="{Binding SelectedFiles}"> </CollectionView>
关键修改说明
- ObservableCollection的优势:它继承自
INotifyCollectionChanged,增删元素时自动通知UI更新,无需手动赋值刷新。 - 依赖CommunityToolkit.Mvvm:
[ObservableProperty]自动生成属性的getter/setter及PropertyChanged通知,避免手动实现的冗余和错误。 - 简化逻辑:移除
sourceData与Items的混乱赋值,直接操作ObservableCollection;用LINQ简化重复文件检查逻辑。 - 异步方法规范:
async Task替代async void,便于异常处理和后续功能扩展。
页面代码保持不变
public MainPage(FileViewModel vm) { InitializeComponent(); BindingContext = vm; }
内容的提问来源于stack exchange,提问作者Preeti Jadhav
相关产品推荐
相关产品推荐

