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

.NET MAUI中将ListView的ItemSelected事件绑定至ViewModel时出现编译错误的问题咨询

.NET MAUI中将ListView的ItemSelected事件绑定至ViewModel时出现编译错误的问题咨询

你遇到的这个编译错误,核心原因很明确:ItemSelected是ListView的事件,不是可绑定属性,所以不能直接用{Binding OnItemTappedChanged}这种绑定属性的语法来关联ViewModel里的方法。XAML里的{Binding ...}是用来绑定数据属性的,事件需要用专门的方式来关联到ViewModel的逻辑,下面给你两种符合MVVM思想的解决方案:

方法一:利用SelectedItem绑定结合RelayCommand(推荐)

既然你已经在XAML里绑定了SelectedItem="{Binding SelectedCategory}",完全可以依托这个绑定来处理导航逻辑,不需要再碰ItemSelected事件:

  1. 先在ViewModel里添加一个专门处理导航的RelayCommand(用CommunityToolkit.Mvvm的特性会很方便):
[RelayCommand]
private async Task NavigateToCategoryDetails(CategoryModel category)
{
    // 避免空值触发
    if (category == null) return;
    
    await Shell.Current.GoToAsync(nameof(NewPage1), new Dictionary<string, object>
    {
        { nameof(NewPage1), category }
    });
}
  1. 修改SelectedCategory的setter,在属性变化时调用这个命令:
public CategoryModel SelectedCategory
{
    get => selectedCategory;
    set
    {
        // 先更新属性,再判断是否触发导航
        if (SetProperty(ref selectedCategory, value) && value != null)
        {
            NavigateToCategoryDetailsCommand.Execute(value);
            // 可选:取消选中状态,这样用户再次点击同一个item还能触发导航
            SelectedCategory = null;
        }
    }
}
  1. 最后把XAML里的ItemSelected="{Binding OnItemTappedChanged}"这一行删掉就好,现在依靠SelectedItem的绑定就能触发导航逻辑了。

方法二:用EventToCommandBehavior把事件转成命令

如果你更习惯直接处理ItemSelected事件,可以用MAUI Community Toolkit提供的EventToCommandBehavior来把事件转化为命令绑定到ViewModel:

  1. 先在XAML里添加MAUI Toolkit的命名空间:
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
  1. 给ListView添加Behavior,关联ItemSelected事件和ViewModel的命令:
<ListView
    ItemsSource="{Binding Categories}"
    HasUnevenRows="True"
    IsPullToRefreshEnabled="True"
    IsRefreshing="{Binding ListRefreshing, Mode=OneWay}"
    RefreshCommand="{Binding RefreshCommand}"
    SelectionMode="Single"
    SelectedItem="{Binding SelectedCategory}">
    
    <!-- 保留你原来的ItemTemplate内容 -->
    
    <ListView.Behaviors>
        <toolkit:EventToCommandBehavior
            EventName="ItemSelected"
            Command="{Binding ItemSelectedCommand}"
            EventArgsConverter="{StaticResource SelectedItemConverter}" />
    </ListView.Behaviors>
</ListView>
  1. 在ViewModel里添加对应的命令:
[RelayCommand]
private async Task ItemSelected(CategoryModel category)
{
    if (category == null) return;
    
    await Shell.Current.GoToAsync(nameof(NewPage1), new Dictionary<string, object>
    {
        { nameof(NewPage1), category }
    });
}
  1. 创建一个转换器,把事件参数SelectedItemChangedEventArgs转成我们需要的CategoryModel:
public class SelectedItemConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is SelectedItemChangedEventArgs args)
        {
            return args.SelectedItem as CategoryModel;
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
  1. 最后在XAML的资源里注册这个转换器:
<ContentPage.Resources>
    <local:SelectedItemConverter x:Key="SelectedItemConverter" />
</ContentPage.Resources>

额外小提示

  • 处理完导航后把SelectedCategory设为null是个好习惯,能避免用户重复点击同一个item时无法触发逻辑的问题。
  • 你原来写的OnItemTappedChanged方法可以删掉了,现在的实现方式更符合MVVM的思想,ViewModel不需要依赖UI层的事件参数。

备注:内容来源于stack exchange,提问作者Gavin Beard

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 08:34:15