List和ObservableCollection和ListBinding在MVVM模式下的对比

List和ObservableCollection和ListBinding在MVVM模式下的对比

List

当对List进行增删操作后,并不会对View进行通知。

csharp 复制代码
//Employee
public class Employee : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;
    public string Name { get; set; }
    private int salary;
    public int Salary
    {
        get { return salary; }
        set
        {
            salary = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Salary)));
        }
    }
}
xml 复制代码
<!--View-->
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition Height="40" />
    </Grid.RowDefinitions>
    <DataGrid ItemsSource="{Binding Employees}" />
    <StackPanel
        Grid.Row="1"
        VerticalAlignment="Center"
        Orientation="Horizontal">
        <Button Command="{Binding addCommand}" Content="Add" />
        <TextBlock Text="工资总额" />
        <TextBox Text="{Binding TotalSalary, Mode=OneWay}" />
    </StackPanel>
</Grid>
csharp 复制代码
//MainViewModel
public partial class MainViewModel:INotifyPropertyChanged
{
    public List<Employee> Employees { get; }
    public int TotalSalary=>Employees.Sum(x => x.Salary);

    
    public MainViewModel()
    {
        Employees = new List<Employee>() { 
            new Employee(){Name="Tom",Salary=200},
            new Employee(){Name="Tim",Salary=450},
            new Employee(){Name="Jerry",Salary=780},
            new Employee(){Name="Jake",Salary=540},
            new Employee(){Name="Kit",Salary=670},
        };
        
    }
    [RelayCommand]
    private void add()
    {
        Employees.Add(new Employee() {  Name = "Lit", Salary = 260 });
        //通知TotalSalay
        PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(nameof(TotalSalary)));
    }

    public event PropertyChangedEventHandler? PropertyChanged;
}

可以看到,点击Add后,上面列表中并没有更新,但是工资总额已经更新,这说明新的数据已经加到了List中,但是List并没有通知View。

ObservableCollection

  • ObservableCollection可以在增加和删除时,对View进行通知

    修改MainViewModel

    csharp 复制代码
    public partial class MainViewModel:INotifyPropertyChanged
    {
        public ObservableCollection<Employee> Employees { get; }
        public int TotalSalary=>Employees.Sum(x => x.Salary);
    
        
        public MainViewModel()
        {
            Employees = new ObservableCollection<Employee>() { 
                new Employee(){Name="Tom",Salary=200},
                new Employee(){Name="Tim",Salary=450},
                new Employee(){Name="Jerry",Salary=780},
                new Employee(){Name="Jake",Salary=540},
                new Employee(){Name="Kit",Salary=670},
            };
            
        }
        [RelayCommand]
        private void add()
        {
            Employees.Add(new Employee() {  Name = "Lit", Salary = 260 });
            PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(nameof(TotalSalary)));
        }
        //增加一个Modify方法
        [RelayCommand]
        private void Modify()
        {
            Employees[2].Salary = 999;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TotalSalary)));
        }
    
        public event PropertyChangedEventHandler? PropertyChanged;
    }

    可以发现,点击Add,View中也相应地进行了更新,而且工资总额也相应改变。同时,无论是add还是Modify,都使用了PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TotalSalary)));它的改进做法是使用CollectionChanged事件。

csharp 复制代码
//改进做法,增加CollectionChanged,可以删除add()和Modify()的PropertyChanged...了
Employees.CollectionChanged += (_, _) => { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TotalSalary))); };

BindingList

BindingList提供了更多的功能,提供了排序、搜索、过滤等功能。此外,BindingList 还提供了对数据源的更多控制,如 AllowNew、AllowEdit 和 AllowRemove 属性,用于控制是否允许添加、编辑和删除项。

BindingList提供了ListChanged事件,该事件参数中提供了详细的信息,但是ObservableCollection 是线程安全的,可以在多个线程中使用。而 BindingList 不是线程安全的,如果需要在多个线程中使用,需要进行额外的线程同步处理。

相关推荐
AI袋鼠帝11 小时前
Claude4.5+Gemini3 接管电脑桌面,这回是真无敌了..
人工智能·windows·aigc
獨枭11 小时前
Windows 下安装与使用 Miniconda 完整指南
windows
命里有定数13 小时前
保姆级教程:在 Windows (WSL2) 下本地部署 Qwen3-ASR
windows
聆风吟º13 小时前
CANN hccl 深度解析:异构计算集群通信库的跨节点通信与资源管控实现逻辑
人工智能·wpf·transformer·cann
lucky670716 小时前
Windows 上彻底卸载 Node.js
windows·node.js
编程小白202616 小时前
从 C++ 基础到效率翻倍:Qt 开发环境搭建与Windows 神级快捷键指南
开发语言·c++·windows·qt·学习
铉铉这波能秀17 小时前
LeetCode Hot100数据结构背景知识之列表(List)Python2026新版
数据结构·leetcode·list
凯子坚持 c18 小时前
CANN 性能剖析实战:从原始事件到交互式火焰图
windows·microsoft
开开心心就好19 小时前
发票合并打印工具,多页布局设置实时预览
linux·运维·服务器·windows·pdf·harmonyos·1024程序员节
獨枭19 小时前
PyCharm 跑通 SAM 全流程实战
windows