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

.NET MAUI MVVM模式下驾驶员删除异常及构造函数参数错误解决

解决.NET MAUI MVVM中的构造参数不匹配与删除功能实现问题

让我们一步步解决你遇到的两个核心问题:CS7036参数不匹配错误和详情页删除功能。

一、先解决CS7036构造参数不匹配错误

这个错误的根源是你的ProfilPilotePage构造函数要求传入PageListPiloteViewModel,但你在跳转时却试图传入ProfilPiloteViewModel并直接设置BindingContext,类型完全不匹配。我们需要调整页面与ViewModel的对应关系:

1. 修改ProfilPilotePage的构造函数

让页面接收自己对应的ProfilPiloteViewModel,而不是列表的ViewModel:

public partial class ProfilPilotePage : ContentPage
{
    private readonly ProfilPiloteViewModel _viewModel;

    public ProfilPilotePage(ProfilPiloteViewModel viewModel)
    {
        InitializeComponent();
        _viewModel = viewModel;
        BindingContext = _viewModel;
    }
}

2. 修正页面跳转代码

在PageListPiloteView的SelectionnerPilote方法中,正确创建ProfilPiloteViewModel并传入构造参数,再传递给页面:

private async void SelectionnerPilote(object sender, SelectionChangedEventArgs e)
{
    // 安全获取选中的驾驶员
    if (e.CurrentSelection.FirstOrDefault() is not PiloteModel selectedPilote) return;
    
    // 获取当前页面的列表ViewModel(假设页面的BindingContext是PageListPiloteViewModel)
    if (BindingContext is not PageListPiloteViewModel listViewModel) return;
    
    // 创建详情ViewModel,传入选中的驾驶员和列表ViewModel引用(用于删除)
    var profileViewModel = new ProfilPiloteViewModel(selectedPilote, listViewModel);
    
    // 正确传入构造参数,解决CS7036错误
    await Navigation.PushAsync(new ProfilPilotePage(profileViewModel));
}

二、实现详情页删除功能

删除功能需要让详情页能操作列表中的ObservableCollection<PiloteModel>,这里推荐两种方案,选一种适合你的:

方案一:通过ViewModel引用直接操作列表(简单直接)

让ProfilPiloteViewModel持有PageListPiloteViewModel的引用,直接从集合中移除选中的驾驶员:

1. 完善ProfilPiloteViewModel

public class ProfilPiloteViewModel : INotifyPropertyChanged
{
    private PiloteModel _pilote;
    public PiloteModel Pilote
    {
        get => _pilote;
        set { _pilote = value; OnPropertyChanged(); }
    }

    private readonly PageListPiloteViewModel _listViewModel;
    public ICommand SupprimerPiloteCommand { get; }

    // 构造函数接收选中的驾驶员和列表ViewModel
    public ProfilPiloteViewModel(PiloteModel selectedPilote, PageListPiloteViewModel listViewModel)
    {
        Pilote = selectedPilote;
        _listViewModel = listViewModel;
        SupprimerPiloteCommand = new Command(ExecuteSupprimerPilote);
    }

    private void ExecuteSupprimerPilote()
    {
        if (Pilote != null && _listViewModel.ListePilotes.Contains(Pilote))
        {
            _listViewModel.ListePilotes.Remove(Pilote);
            // 删除后关闭详情页
            Application.Current.MainPage.Navigation.PopAsync();
        }
    }

    // 实现INotifyPropertyChanged接口(别忘了这个)
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

2. 修正详情页XAML的按钮绑定

确保按钮绑定到正确的命令,并补充文本:

<Button Text="Supprimer" Command="{Binding SupprimerPiloteCommand}" />

同时修正Entry的Placeholder绑定错误(不需要绑定,直接写静态文本):

<Entry Text="{Binding Pilote.Nom, Mode=TwoWay}" Placeholder="Nom"></Entry>
<Entry Text="{Binding Pilote.Prenom, Mode=TwoWay}" Placeholder="Prénom"></Entry>
<Entry Text="{Binding Pilote.Points, Mode=TwoWay}" Placeholder="Points" Keyboard="Numeric"></Entry>

方案二:通过事件通知列表ViewModel删除(松散耦合)

如果你不想让ViewModel之间直接引用,可以用事件的方式,让详情ViewModel触发删除事件,列表页面订阅事件并执行删除:

1. 修改ProfilPiloteViewModel

添加删除事件,移除列表ViewModel的引用:

public class ProfilPiloteViewModel : INotifyPropertyChanged
{
    private PiloteModel _pilote;
    public PiloteModel Pilote
    {
        get => _pilote;
        set { _pilote = value; OnPropertyChanged(); }
    }

    public ICommand SupprimerPiloteCommand { get; }
    // 定义删除事件
    public event EventHandler<PiloteModel> PiloteSupprime;

    public ProfilPiloteViewModel(PiloteModel selectedPilote)
    {
        Pilote = selectedPilote;
        SupprimerPiloteCommand = new Command(ExecuteSupprimerPilote);
    }

    private void ExecuteSupprimerPilote()
    {
        if (Pilote != null)
        {
            // 触发删除事件
            PiloteSupprime?.Invoke(this, Pilote);
            Application.Current.MainPage.Navigation.PopAsync();
        }
    }

    // 实现INotifyPropertyChanged接口
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

2. 调整跳转代码订阅事件

private async void SelectionnerPilote(object sender, SelectionChangedEventArgs e)
{
    if (e.CurrentSelection.FirstOrDefault() is not PiloteModel selectedPilote) return;
    if (BindingContext is not PageListPiloteViewModel listViewModel) return;
    
    var profileViewModel = new ProfilPiloteViewModel(selectedPilote);
    // 订阅删除事件,在事件处理中移除驾驶员
    profileViewModel.PiloteSupprime += (s, pilote) => 
    {
        if (listViewModel.ListePilotes.Contains(pilote))
            listViewModel.ListePilotes.Remove(pilote);
    };
    
    await Navigation.PushAsync(new ProfilPilotePage(profileViewModel));
}

额外的小优化

  • 在PageListPiloteViewModel中,你之前定义的OnsupprimerPiloteCommand可以移除了,因为删除逻辑已经移到详情ViewModel中;
  • 确保ListePilotes是public的,这样其他ViewModel才能访问它;
  • 在集合选择时,记得清空选中状态(可选):((CollectionView)sender).SelectedItem = null;,避免重复选中同一个项。

内容的提问来源于stack exchange,提问作者Eloi Jahan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 17:10:48