WPF中双向绑定通知机制之ObservableCollection使用
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
WPF中双向绑定通知机制之ObservableCollection使⽤
msdn中 ObservableCollection<T> 类表⽰⼀个动态数据集合,在添加项、移除项或刷新整个列表时,此集合将提供通知。
在许多情况下,所使⽤的数据是对象的集合。
例如,数据绑定中的⼀个常见⽅案是使⽤(如、或)来显⽰记录的集合。
可以枚举实现接⼝的任何集合。
但是,若要设置动态绑定,以便集合中的插⼊或删除操作可以⾃动更新 UI,则该集合必须实现接⼝。
此接⼝公开事件,只要基础集合发⽣更改,都应该引发该事件。
WPF 提供 ObservableCollection<T> 类,它是实现接⼝的数据集合的内置实现。
还有许多情况,我们所使⽤的数据只是单纯的字段或者属性,此时我们需要为这些字段或属性实现INotifyPropertyChanged接⼝,实现了该接⼝,只要字段或属性的发⽣了改变,就会提供通知机制。
ObservableCollection<T>实现
前台xmal
<Window x:Class="WpfApplication1.WindowObservable"
xmlns="/winfx/2006/xaml/presentation"
xmlns:x="/winfx/2006/xaml"
Title="Window8" Height="356" Width="471">
<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>
后台cs
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 ponentModel;
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; }
}
}
}
在这个例⼦中我们将Students数据对象⽤ObservableCollection<T>来修饰。
这样当我们点击click的时候我们看到。
当我们点击后只有student整个对象的改变引发了后台通知机制。
INotifyPropertyChanged实现
INotifyPropertyChanged会向客户端发出某⼀属性值已更改的通知。
当元素属性值改变时,会通知后台model
前台代码不变,我们让后台Students Model实现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 ponentModel;
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 : 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;
}
}
}
此时我们再运⾏代码会发现
使⽤DataContext为页⾯对象设置上下⽂
不管是集合还是对象都发⽣了改变。
⾄此。
我们的整个后台通知就能完美监视任何对象变动。
但是现在还有⼀个问题。
我们如果在点击事件⾥⾯给infos赋值⼀个新的集合数据。
如下
private void button1_Click(object sender, RoutedEventArgs e)
{
infos[1] = new Students() { Id = 4, Age = 14, Name = "这是⼀个集合改变" };
infos[2].Name = "这是⼀个属性改变";
infos = new ObservableCollection<Students>() {
new Students(){ Id=1, Age=11, Name="这是改变后的集合"},
new Students(){ Id=2, Age=12, Name="这是改变后的集合"},
new Students(){ Id=3, Age=13, Name="这是改变后的集合"},
new Students(){ Id=4, Age=14, Name="这是改变后的集合"}
};
}
会发现数据并没有变更。
这是为什么?我们明明实现了ObservableCollection<T>类型啊。
这是因为infos这个集合的地址变更并没有实现通知机制。
当我们new⼀个对象赋值给infos时候,infos的地址指向变更了。
所以集合⾥⾯数据的变化,infos变更后的数据就参与绑定了。
我们这时候可以通过DataContext实现数据数据项的变更通知。
我们添加⼀个ViewModel类,实现INotifyPropertyChanged接⼝
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));
}
}
}
windowsObservable类修改为如下
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 = "这是⼀个属性改变";
}
}
我们给xaml listbox设置如下绑定
ItemsSource="{Binding StudentList, Mode=TwoWay}"
运⾏程序我们发现集合的改变也会被通知到前台。
代码参考:/fwj380891124/article/details/8194190本⽂地址:
博客地址:
转载请以超链接形式标明⽂章原始出处。