ObservableCollection和List的区别及WPF中的使用

ObservableCollection和List的区别

ObservableCollection

ObservableCollection继承了Collection,INotifyCollectionChanged,INotifyPropertyChanged

  • Collection:为泛型集合提供基类
  • INotifyCollectionChanged:将集合的动态更改通知给侦听器,例:何时添加或移除项或者重置整个集合对象。
  • INotifyPropertyChanged:向客户端发出某一属性值已经更改的通知

ObservableCollection表示一个动态数据集合,在添加项、移除项或刷新整个列表时,此集合将提供通知。

List

List继承了IList,ICollection,IEnumerable,IList,ICollection,IEnumerable

  • IList:表示可按照索引单独访问的一组对象
  • ICollection:定义操作泛型集合的方法
  • IEnmerable:公开枚举器,改枚举器支持在指定类型的集合上进行简单迭代
  • IList:表示可按照索引单独访问的对象的非泛型集合
  • ICollection:定义所有非泛型集合的大小、枚举器和同步方法
  • IEnumerable:公开枚举器,该枚举器支持在非泛型集合上进行简单迭代

List表示可通过索引访问的对象的强类型列表。提供用于对列表进行搜索、排序和操作的方法。

案例一:需要增添、移除项

代码

<ListBox x:Name="listbind" Height="61" HorizontalAlignment="Left" Margin="146,12,0,0" VerticalAlignment="Top" Width="120" >
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
<ListBox x:Name="observbind" Height="74" HorizontalAlignment="Left" Margin="146,111,0,0" VerticalAlignment="Top" Width="120" >
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
<TextBlock Height="23" HorizontalAlignment="Left" Margin="38,58,0,0" Name="textBlock1" Text="List绑定数据" VerticalAlignment="Top" />
<TextBlock Height="44" HorizontalAlignment="Left" Margin="12,125,0,0" Name="textBlock2" Text="ObservableCollection绑定数据" VerticalAlignment="Top" Width="112" />
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="77,211,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
private List<Person> person1 = new List<Person>();
private ObservableCollection<Person> person2 = new ObservableCollection<Person>();

public Demo()
{
    InitializeComponent();
    person1.Add(new Person() { Name = "张三" });
    person1.Add(new Person() { Name = "李四" });
    listbind.ItemsSource = person1;
    person2.Add(new Person() { Name = "张三" });
    person2.Add(new Person() { Name = "李四" });
    observbind.ItemsSource = person2;
}

private void button1_Click(object sender, RoutedEventArgs e)
{
    person1.Add(new Person() { Name = "王五" });
    person2.Add(new Person() { Name = "王五" });
}
public class Person  
{  
     public string Name { get; set; }  
}  

运行结果

运行程序点击button按钮,然后只有ObservableCollection的有添加,这表示当集合对象的集合改变时,只有ObservableCollection会发出通知更新UI。

案例二:需要修改字段或属性

如果只需要修改字段或属性,需要将绑定的类继承INotifyPropertyChanged

未添加INotifyPropertyChanged的代码

<Window x:Class="WpfApplication1.WindowObservable"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="" Height="400" Width="600">
    <Grid>
        <StackPanel Height="295" HorizontalAlignment="Left" Margin="10,10,0,0" Name="stackPanel1" VerticalAlignment="Top" Width="427">
            <TextBlock Height="23" Name="textBlock1" Text="编号:" />
            <TextBox Height="23" Name="txtStudentId" Width="301" HorizontalAlignment="Left"/>
            <TextBlock Height="23" Name="textBlock2" Text="列表:" />
            <ListBox Height="156" Name="lbStudent" Width="305" HorizontalAlignment="Left">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Name="stackPanel2" Orientation="Horizontal">
                            <TextBlock  Text="{Binding Id,Mode=TwoWay}" Margin="5" Background="Beige"/>
                            <TextBlock Text="{Binding Name,Mode=TwoWay}" Margin="5"/>
                            <TextBlock  Text="{Binding Age,Mode=TwoWay}" Margin="5"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
            <Button Content="Button" Height="23" Name="button1" Width="75" HorizontalAlignment="Left" Click="button1_Click" />
        </StackPanel>
    </Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace WpfApplication1
{
    public partial class WindowObservable : Window
    {
        ObservableCollection<Students> infos = new ObservableCollection<Students>() 		{ 
            new Students(){ Id=1, Age=11, Name="Tom"},
            new Students(){ Id=2, Age=12, Name="Darren"},
            new Students(){ Id=3, Age=13, Name="Jacky"},
            new Students(){ Id=4, Age=14, Name="Andy"}
            };

        public WindowObservable()
        {
            InitializeComponent();

            this.lbStudent.ItemsSource = infos;

            this.txtStudentId.SetBinding(TextBox.TextProperty, new Binding("SelectedItem.Id") { Source = lbStudent });
        }
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            infos[1] = new Students() { Id = 4, Age = 14, Name = "这是一个集合改变" };
            infos[2].Name = "这是一个属性改变";
        }

    }
    public class Students
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }  
}

运行结果

此时,点击按钮后,Name属性值,没有任何改变

添加INotifyPropertyChanged的代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace WpfApplication1
{
    public partial class WindowObservable : Window
    {
        ObservableCollection<Students> infos = new ObservableCollection<Students>() 		{ 
            new Students(){ Id=1, Age=11, Name="Tom"},
            new Students(){ Id=2, Age=12, Name="Darren"},
            new Students(){ Id=3, Age=13, Name="Jacky"},
            new Students(){ Id=4, Age=14, Name="Andy"}
            };

        public WindowObservable()
        {
            InitializeComponent();

            this.lbStudent.ItemsSource = infos;

            this.txtStudentId.SetBinding(TextBox.TextProperty, new Binding("SelectedItem.Id") { Source = lbStudent });
        }
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            infos[1] = new Students() { Id = 4, Age = 14, Name = "这是一个集合改变" };
            infos[2].Name = "这是一个属性改变";
        }
        
    }
    //此处继承INotifyPropertyChanged接口
    public class Students : INotifyPropertyChanged
    {
        string _name;
        public int Id { get; set; }
        public string Name
        {
            get { return _name; }
            set { _name = value; OnPropertyChanged("Name"); }
        }
        public int Age { get; set; }
        protected internal virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
}

运行结果

此时,点击按钮后,Name属性值改变

案例三:赋予一个新的集合

当我们需要赋予一个新的集合给绑定的集合数据时,因为新的集合会生成新的地址,所以并没有实现通知机制。此时我们需要通过DataContext实现数据项的变更通知。

代码

<Window x:Class="WpfApplication1.WindowObservable"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="" Height="400" Width="600">
    <Grid>
        <StackPanel Height="295" HorizontalAlignment="Left" Margin="10,10,0,0" Name="stackPanel1" VerticalAlignment="Top" Width="427">
            <TextBlock Height="23" Name="textBlock1" Text="编号:" />
            <TextBox Height="23" Name="txtStudentId" Width="301" HorizontalAlignment="Left"/>
            <TextBlock Height="23" Name="textBlock2" Text="列表:" />
            <ListBox Height="156" Name="lbStudent" Width="305" HorizontalAlignment="Left" ItemsSource="{Binding StudentList, Mode=TwoWay}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Name="stackPanel2" Orientation="Horizontal">
                            <TextBlock  Text="{Binding Id,Mode=TwoWay}" Margin="5" Background="Beige"/>
                            <TextBlock Text="{Binding Name,Mode=TwoWay}" Margin="5"/>
                            <TextBlock  Text="{Binding Age,Mode=TwoWay}" Margin="5"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
            <Button Content="Button" Height="23" Name="button1" Width="75" HorizontalAlignment="Left" Click="button1_Click" />
        </StackPanel>
    </Grid>
</Window>
public class ViewModel : INotifyPropertyChanged
{
    private ObservableCollection<Students> studentList;
    public ObservableCollection<Students> StudentList
    {
        get
        {
            return this.studentList;
        }
        set
        {
            if (this.studentList != value)
            {
                this.studentList = value;
                OnPropertyChanged("StudentList");
            }
        }
    }
    
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
public partial class WindowObservable : Window
{
    ViewModel viewModel = new ViewModel();
    
    public WindowObservable()
    {
        InitializeComponent();
        viewModel.StudentList = new ObservableCollection<Students>() { 
            new Students(){ Id=1, Age=11, Name="Tom"},
            new Students(){ Id=2, Age=12, Name="Darren"},
            new Students(){ Id=3, Age=13, Name="Jacky"},
            new Students(){ Id=4, Age=14, Name="Andy"}
        };
        this.lbStudent.DataContext = viewModel;
    }
    
    private void button1_Click(object sender, RoutedEventArgs e)
    {
        viewModel.StudentList[1] = new Students() { Id = 4, Age = 14, Name = "这是一个集合改变" };

        viewModel.StudentList = new ObservableCollection<Students>() { 
            new Students(){ Id=19, Age=111, Name="这是变化后的几何"},
            new Students(){ Id=29, Age=121, Name="这是变化后的几何"},
            new Students(){ Id=39, Age=131, Name="这是变化后的几何"},
            new Students(){ Id=49, Age=141, Name="这是变化后的几何"}
        };
        viewModel.StudentList[2].Name = "这是一个属性改变";
    }
}

运行结果

此时,当我们点击按钮,会生成新的集合对象,并动态显示在ListBox中

本文参考借鉴整理于以下博客,用于个人记录
ObservableCollection和List的区别总结: ObservableCollection和List的区别总结
WPF 中双向绑定通知机制之ObservableCollection使用:WPF 中双向绑定通知机制之ObservableCollection使用

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值