You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MVVM模式从文件选择器填充CollectionView的问题

MVVM模式下CollectionView无法展示选中文件的问题解决

问题核心原因

你的ViewModel存在三个关键问题导致UI无法更新:

  1. 集合类型错误:使用List<Item>而非ObservableCollection<Item>,List的增删操作不会触发UI绑定的属性变更通知。
  2. 属性通知缺失:手动定义的Items属性没有实现INotifyPropertyChanged,即使赋值也无法通知CollectionView更新。
  3. 逻辑混乱: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>

关键修改说明

  1. ObservableCollection的优势:它继承自INotifyCollectionChanged,增删元素时自动通知UI更新,无需手动赋值刷新。
  2. 依赖CommunityToolkit.Mvvm:[ObservableProperty]自动生成属性的getter/setter及PropertyChanged通知,避免手动实现的冗余和错误。
  3. 简化逻辑:移除sourceData与Items的混乱赋值,直接操作ObservableCollection;用LINQ简化重复文件检查逻辑。
  4. 异步方法规范:async Task替代async void,便于异常处理和后续功能扩展。

页面代码保持不变

public MainPage(FileViewModel vm)
{
    InitializeComponent();
    BindingContext = vm;
}

内容的提问来源于stack exchange,提问作者Preeti Jadhav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 19:00:32