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

在许多情况下,所使用的数据是对象的集合。 例如,数据绑定中的一个常见方案是使用 ItemsControl(如 ListBoxListView 或 TreeView)来显示记录的集合。

可以枚举实现 IEnumerable 接口的任何集合。 但是,若要设置动态绑定,以便集合中的插入或删除操作可以自动更新 UI,则该集合必须实现 INotifyCollectionChanged 接口。 此接口公开 CollectionChanged 事件,只要基础集合发生更改,都应该引发该事件。

WPF 提供 ObservableCollection<T> 类,它是实现 INotifyCollectionChanged 接口的数据集合的内置实现。

还有许多情况,我们所使用的数据只是单纯的字段或者属性,此时我们需要为这些字段或属性实现INotifyPropertyChanged接口,实现了该接口,只要字段或属性的发生了改变,就会提供通知机制。

ObservableCollection<T>实现

前台xmal

<Window x:Class="WpfApplication1.WindowObservable"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window8" Height="" Width="">
<Grid>
<StackPanel Height="" HorizontalAlignment="Left" Margin="10,10,0,0" Name="stackPanel1" VerticalAlignment="Top" Width="">
<TextBlock Height="" Name="textBlock1" Text="学员编号:" />
<TextBox Height="" Name="txtStudentId" Width="" HorizontalAlignment="Left"/>
<TextBlock Height="" Name="textBlock2" Text="学员列表:" />
<ListBox Height="" Name="lbStudent" Width="" HorizontalAlignment="Left">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Name="stackPanel2" Orientation="Horizontal">
<TextBlock Text="{Binding Id,Mode=TwoWay}" Margin="" Background="Beige"/>
<TextBlock Text="{Binding Name,Mode=TwoWay}" Margin=""/>
<TextBlock Text="{Binding Age,Mode=TwoWay}" Margin=""/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Content="Button" Height="" Name="button1" Width="" 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 System.ComponentModel; namespace WpfApplication1
{
public partial class WindowObservable : Window
{
ObservableCollection<Students> infos = new ObservableCollection<Students>() {
new Students(){ Id=, Age=, Name="Tom"},
new Students(){ Id=, Age=, Name="Darren"},
new Students(){ Id=, Age=, Name="Jacky"},
new Students(){ Id=, Age=, 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[] = new Students() { Id = , Age = , Name = "这是一个集合改变" };
infos[].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 System.ComponentModel; namespace WpfApplication1
{
public partial class WindowObservable : Window
{
ObservableCollection<Students> infos = new ObservableCollection<Students>() {
new Students(){ Id=, Age=, Name="Tom"},
new Students(){ Id=, Age=, Name="Darren"},
new Students(){ Id=, Age=, Name="Jacky"},
new Students(){ Id=, Age=, 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[] = new Students() { Id = , Age = , Name = "这是一个集合改变" };
infos[].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[] = new Students() { Id = , Age = , Name = "这是一个集合改变" };
infos[].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=, Age=, Name="Tom"},
new Students(){ Id=, Age=, Name="Darren"},
new Students(){ Id=, Age=, Name="Jacky"},
new Students(){ Id=, Age=, Name="Andy"}
};
this.lbStudent.DataContext = viewModel;
}
private void button1_Click(object sender, RoutedEventArgs e)
{
viewModel.StudentList[] = new Students() { Id = , Age = , Name = "这是一个集合改变" }; viewModel.StudentList = new ObservableCollection<Students>() {
new Students(){ Id=, Age=, Name="这是变化后的几何"},
new Students(){ Id=, Age=, Name="这是变化后的几何"},
new Students(){ Id=, Age=, Name="这是变化后的几何"},
new Students(){ Id=, Age=, Name="这是变化后的几何"}
};
viewModel.StudentList[].Name = "这是一个属性改变";
}
}

我们给xaml listbox设置如下绑定

ItemsSource="{Binding StudentList, Mode=TwoWay}"

运行程序我们发现集合的改变也会被通知到前台。

代码参考:http://blog.csdn.net/fwj380891124/article/details/8194190

本文地址:http://www.cnblogs.com/santian/p/4366832.html

博客地址:http://www.cnblogs.com/santian/

转载请以超链接形式标明文章原始出处。

WPF 中双向绑定通知机制之ObservableCollection使用的更多相关文章

  1. 【WPF】WPF DataGrid List数据源 双向绑定通知机制之ObservableCollection使用以及MultiBinding 的应用

    以下代码实现了DataGrid的简单绑定List数据源 重点要提一下的是,绑定List数据源,但是不能直接用List.比如下面的代码,使用List<GridItem>只能实现数据修改的绑定 ...

  2. WPF数据双向绑定

    设置双向绑定,首先控件要绑定的对象要先继承一个接口: INotifyPropertyChanged 然后对应被绑定的属性增加代码如下: 意思就是当Age这个属性变化时,要通知监听它变化的人. 即:Pr ...

  3. 浅析SQL Server 2005中的主动式通知机制

    一.引言 在开发多人同时访问的Web应用程序(其实不只这类程序)时,开发人员往往会在缓存策略的设计上狠下功夫.这是因为,如果将这种环境下不常变更的数据临时存放在应用程序服务器或是用户机器上的话,可以避 ...

  4. 封装:WPF中可以绑定的BindPassWord控件

    原文:封装:WPF中可以绑定的BindPassWord控件 一.目的:本身自带的PassWord不支持绑定 二.Xaml部分 <UserControl x:Class="HeBianG ...

  5. C# Wpf集合双向绑定

    说明: msdn中   ObservableCollection<T> 类    表示一个动态数据集合,在添加项.移除项或刷新整个列表时,此集合将提供通知. 在许多情况下,所使用的数据是对 ...

  6. inotify--内核中文件系统的通知机制

    转载:http://www.ibm.com/developerworks/cn/linux/l-inotifynew/index.html 一. 引言 众所周知,Linux 桌面系统与 MAC 或 W ...

  7. vue.js 中双向绑定的实现---初级

    1. 1 我们看到的变量,其实都不是独立的,它们都是windows对象上的属性 <!DOCTYPE html> <html lang="en"> <h ...

  8. ComboBox在WPF中的绑定示例:绑定项、集合、转换,及其源代码

    示例1.Selector(基类) 的示例Controls/SelectionControl/SelectorDemo.xaml <Page x:Class="Windows10.Con ...

  9. <转>WPF 中的绑定

    在WPF应用的开发过程中Binding是一个非常重要的部分. 在实际开发过程中Binding的不同种写法达到的效果相同但事实是存在很大区别的. 这里将实际中碰到过的问题做下汇总记录和理解. 1. so ...

随机推荐

  1. 各种Lisp系语言大检阅

    主要特色: CommonLISP : lisp系集大成者, 工业化强度的大型语言. 拥有理论上最高的表达力, 非常复杂, 学习难度极大. 喜欢的人捧到天上, 觉得它是一切语言的终点, 不喜欢的人恶心死 ...

  2. linux下GPRS模块ppp拨号上网

    ---------------------------------------------------------------------------------------------------- ...

  3. csharp 面向对象编程

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Shap ...

  4. Vue实例总结

    一.登陆框的要点总结: 1.暂无数据就是要myData里没数据时候才出来:删除全部就是要有数据才出来.v-show的使用: 2.表格行就是需要循环数据,v-for.{{$index}}.{{item. ...

  5. Oracle中分页查询语句的写法

    要动态的变化分页查询的条件,比如pageNow 这个变量表示的是当前是第几页, oracle分页有通用写法,假设一页5行 select * from ( select t.*,rownum rn fr ...

  6. 对AOP切面的一些整理与理解

      首先上一张AOP的图示 一:几个重要的概念   1> 切面:横切关注点(跨越应用程序多个模块的功能)被模块化的特殊对象[验证切面.日志切面]   2> 通知:切面中的每个方法   3& ...

  7. 获取 input 输入框的值

    1.使用原生javascript: 方法一: <html> <head> <script language="javascript"> func ...

  8. iOS 计步器的几种实现方式

    代码地址如下:http://www.demodashi.com/demo/11658.html 这篇文章介绍两种可以获取计步数据的方法,一种是采用CMPedometer获取手机计步器数据,另一种是采用 ...

  9. node.js 学习03

    node.js学习03 解决浏览器接收服务端信息之后乱码的问题: 服务器通过设置http响应报文头,告诉浏览器使用相应的编码 来解析网页. res.setHeader('Content','text/ ...

  10. asp.net core mvc视频A:笔记5-1.路由规则

    方法一:通过MapRoute方法,配置文件位置 小例子:如果所有路径都要在admin下,可以这样写 方法二:通过路由属性 相对路由 现在需要加/admin/home/index才能正常访问原来的默认页 ...