1. ObservableCollection<T> 类 表示一个动态数据集合,在添加项、移除项或刷新整个列表时,此集合将提供通知。
为什么ObservableCollection<T> 绑定后能自动更新UI ?
ObservableCollection<T> 类,它是实现 INotifyCollectionChanged 接口的数据集合的内置实现。
2. 还有一种情况(T类型) 对象的属性 发生变化时 需要通知到UI界面,此时就需要T类型实现 INotifyPropertyChange接口。比如下面例子中的 Students 就需要实现INotifyPropertyChange 接口
3.我们如果在点击事件里面给infos赋值一个新的集合数据。会发现数据并没有变更。这是因为infos这个集合的地址变更并没有实现通知机制。当我们new一个对象赋值给infos时候,infos的地址指向变更了。 解决方式 我们写了一个ViewModel类,并实现INotifyPropertyChanged接口,ViewModel类里面有一个属性
ObservableCollection<Students> StudentList。也是说我们进一步封装,将数据源封装成 ViewModel类的属性。
由此可见 WPF的数据绑定 要求绑定的对象地址不能发生变化,也就是赋值给DataContext的对象地址不能发生变化, 变化的只是对象里面的属性.
界面代码
<Window x:Class="ObservableCollection集合绑定.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ObservableCollection集合绑定"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<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}">
<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>
C#后台代码:
public partial class MainWindow : Window
{
readonly ViewModel viewModel = new ViewModel();
public MainWindow()
{
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;
//创建绑定对象
var binding = new Binding("SelectedItem.Id");
//设置绑定源
binding.Source = lbStudent;
binding.Mode = BindingMode.OneWay;
this.txtStudentId.SetBinding(TextBox.TextProperty, binding);
}
private void button1_Click(object sender, RoutedEventArgs e)
{
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 = "这是一个属性改变";
}
}
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)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
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)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}