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

如何在.NET MAUI的MVVM架构中用List绑定ListView或CollectionView展示数据

.NET MAUI MVVM下绑定ListView/CollectionView并实现动态更新

核心前提:用ObservableCollection替代List

普通List<T>没有实现集合变更通知接口,底层数据增删改时UI不会自动刷新。必须换成ObservableCollection<T>——它实现了INotifyCollectionChanged接口,能在集合元素变化时自动触发UI更新。

同时你的ViewModel需要实现INotifyPropertyChanged接口,确保属性值变更时能通知绑定的UI控件。


分步实现

1. 定义数据实体类

先创建要展示的数据模型,比如一个待办项:

public class TodoItem
{
    public string Title { get; set; }
    public bool IsCompleted { get; set; }
}

如果需要单个实体属性变更时UI同步刷新,TodoItem也需要实现INotifyPropertyChanged接口

2. 实现ViewModel

ViewModel要继承实现INotifyPropertyChanged的基类,或直接使用CommunityToolkit.Mvvm简化开发:

方式一:手动实现INotifyPropertyChanged

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;

public class BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class TodoViewModel : BaseViewModel
{
    private ObservableCollection<TodoItem> _todoItems;
    public ObservableCollection<TodoItem> TodoItems
    {
        get => _todoItems;
        set
        {
            _todoItems = value;
            OnPropertyChanged();
        }
    }

    // 示例:添加数据方法
    public void AddTodoItem()
    {
        TodoItems.Add(new TodoItem { Title = $"新待办项 {TodoItems.Count + 1}" });
    }

    // 示例:删除数据方法
    public void RemoveLastTodoItem()
    {
        if (TodoItems.Count > 0)
            TodoItems.RemoveAt(TodoItems.Count - 1);
    }

    public TodoViewModel()
    {
        // 初始化测试数据
        TodoItems = new ObservableCollection<TodoItem>
        {
            new TodoItem { Title = "完成MAUI绑定教程", IsCompleted = false },
            new TodoItem { Title = "测试动态更新", IsCompleted = true }
        };
    }
}

方式二:用CommunityToolkit.Mvvm(推荐)

先安装CommunityToolkit.Mvvm NuGet包,ViewModel可以更简洁:

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;

public partial class TodoViewModel : ObservableObject
{
    [ObservableProperty]
    private ObservableCollection<TodoItem> _todoItems;

    [RelayCommand]
    public void AddTodoItem()
    {
        TodoItems.Add(new TodoItem { Title = $"新待办项 {TodoItems.Count + 1}" });
    }

    [RelayCommand]
    public void RemoveLastTodoItem()
    {
        if (TodoItems.Count > 0)
            TodoItems.RemoveAt(TodoItems.Count - 1);
    }

    public TodoViewModel()
    {
        TodoItems = new ObservableCollection<TodoItem>
        {
            new TodoItem { Title = "完成MAUI绑定教程", IsCompleted = false },
            new TodoItem { Title = "测试动态更新", IsCompleted = true }
        };
    }
}

3. XAML页面绑定CollectionView(推荐)

CollectionView是MAUI官方推荐的列表控件,比ListView更灵活。在XAML中设置ItemsSource绑定到ViewModel的集合属性,通过ItemTemplate定义项布局:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:vm="clr-namespace:YourAppNamespace.ViewModels"
             x:Class="YourAppNamespace.Views.TodoPage"
             Title="待办列表">

    <!-- 设置页面BindingContext -->
    <ContentPage.BindingContext>
        <vm:TodoViewModel />
    </ContentPage.BindingContext>

    <VerticalStackLayout Padding="10" Spacing="10">
        <!-- 测试按钮:触发数据变更 -->
        <Button Text="添加待办" Command="{Binding AddTodoItemCommand}" />
        <Button Text="删除最后一项" Command="{Binding RemoveLastTodoItemCommand}" />

        <!-- CollectionView绑定数据源 -->
        <CollectionView ItemsSource="{Binding TodoItems}" Margin="0,10,0,0">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <HorizontalStackLayout Spacing="10" Padding="5">
                        <CheckBox IsChecked="{Binding IsCompleted}" />
                        <Label Text="{Binding Title}" 
                               FontSize="16"
                               HorizontalOptions="FillAndExpand" />
                    </HorizontalStackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </VerticalStackLayout>
</ContentPage>

4. (可选)绑定ListView

如果需要使用ListView,写法类似:

<ListView ItemsSource="{Binding TodoItems}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <HorizontalStackLayout Spacing="10" Padding="5">
                    <CheckBox IsChecked="{Binding IsCompleted}" />
                    <Label Text="{Binding Title}" FontSize="16" />
                </HorizontalStackLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

关键注意事项

  • 必须使用ObservableCollection<T>而非List<T>,否则增删元素时UI不会刷新。
  • ViewModel必须实现INotifyPropertyChanged,确保集合属性本身重新赋值时能通知UI。
  • 绑定路径要准确:ItemsSource="{Binding TodoItems}"中的TodoItems必须是ViewModel的公共属性。
  • 若实体属性变更需要同步UI,实体类也需实现INotifyPropertyChanged。

内容的提问来源于stack exchange,提问作者Haseeb Ahmad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 10:23:34