silverlight简单数据绑定3
3种数据绑定模式 OneTime(一次绑定) OneWay(单项绑定) TwoWay(双向绑定)
OneTime:仅在数据绑定创建时使用数据源更新目标。
列子:
第一步,创建数据源对象让Person类实现INotifyPropertyChanged接口,该接口具有PropertyChanged事件,PropertyChanged事件在数据源发生变化时候通知绑定
.cs
namespace SilverlightApplication2
{
public class Person:INotifyPropertyChanged
{ public event PropertyChangedEventHandler PropertyChanged; private String _Name;
public String Name
{
get { return this._Name; }
set
{
this._Name = value;
NotifyPropertyChanged("Name");
}
} private int _Age;
public int Age
{
get { return this._Age; }
set
{
this._Age = value;
NotifyPropertyChanged("Age"); }
} private String _Address;
public String Address
{
get { return this._Address; }
set
{
this._Address = value;
NotifyPropertyChanged("Address");
}
} public void NotifyPropertyChanged(String propertyName)
{
if(PropertyChanged!=null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
} } }
关于INotifyPropertyChanged 参见http://www.cnblogs.com/beginor/archive/2012/08/13/2636418.html
关于 谈谈INotifyPropertyChanged 的实现
参见http://www.cnblogs.com/beginor/archive/2012/08/13/2636418.html
INotifyPropertyChanged 接口是 WPF/Silverlight 开发中非常重要的接口, 它构成了 ViewModel 的基础, 数据绑定基本上都需要这个接口。 所以, 对它的实现也显得非常重要, 下面接贴出我知道的几种实现方式, 希望能起到抛砖引玉的作用。
一般的实现方式
这是一种再普通不过的实现方式, 代码如下:
1
2
3
4
5
6
7
8
9
10
|
public class NotifyPropertyChanged : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; virtual internal protected void OnPropertyChanged( string propertyName) { if ( this .PropertyChanged != null ) { this .PropertyChanged( this , new PropertyChangedEventArgs(propertyName)); } } } |
这种方式称之为一般的实现方式, 因为它确实是太普通不过了, 而且使用起来也让人感到厌恶, 因为必须指定手工指定属性名称:
1
2
3
4
5
6
7
8
9
10
11
12
|
public class MyViewModel : NotifyPropertyChanged { private int _myField; public int MyProperty { get { return _myField; } set { _myField = value; OnPropertyChanged( "MyProperty" ); } } } |
lambda 表达式实现方式
对 lambda 表达式比较熟悉的同学可以考虑用 lambda 表达式实现属性名称传递, 在 NotifyPropertyChanged 类添加一个这样的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
protected void SetProperty<T>( ref T propField, T value, Expression<Func<T>> expr) { var bodyExpr = expr.Body as System.Linq.Expressions.MemberExpression; if (bodyExpr == null ) { throw new ArgumentException( "Expression must be a MemberExpression!" , "expr" ); } var propInfo = bodyExpr.Member as PropertyInfo; if (propInfo == null ) { throw new ArgumentException( "Expression must be a PropertyExpression!" , "expr" ); } var propName = propInfo.Name; propField = value; this .OnPropertyChanged(propName); } |
有了这个方法, NotifyPropertyChanged 基类使用起来就令人舒服了很多:
1
2
3
4
5
6
7
8
9
10
11
|
public class MyViewModel : NotifyPropertyChanged { private int _myField; public int MyProperty { get { return _myField; } set { base .SetProperty( ref _myField, value, () => this .MyProperty); } } } |
这样一来, 把属性名称用字符串传递改成了用 lambda 表达式传递, 减少了硬编码, 确实方便了不少, 但是还是感觉略微麻烦了一些, 还是要写一个 lambda 表达式来传递属性名称。
拦截方式实现
如果对 Castal.DynamicProxy 有印象的话, 可以考虑使用 DynamicProxy 进行拦截实现, 我的实现如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
// 1. 先定义一个拦截器, 重写 PostProcess 方法, 当发现是调用以 set_ 开头的方法时, // 一般就是设置属性了, 可以在这里触发相应的事件。 internal class NotifyPropertyChangedInterceptor : StandardInterceptor { protected override void PostProceed(IInvocation invocation) { base .PostProceed(invocation); var methodName = invocation.Method.Name; if (methodName.StartsWith( "set_" )) { var propertyName = methodName.Substring(4); var target = invocation.Proxy as NotifyPropertyChanged; if (target != null ) { target.OnPropertyChanged(propertyName); } } } } // 2. 再定义一个帮助类, 提供一个工厂方法创建代理类。 public static class ViewModelHelper { private static readonly ProxyGenerator ProxyGenerator = new ProxyGenerator(); private static readonly NotifyPropertyChangedInterceptor Interceptor = new NotifyPropertyChangedInterceptor(); public static T CreateProxy<T>(T obj) where T : class , INotifyPropertyChanged { return ProxyGenerator.CreateClassProxyWithTarget(obj, Interceptor); } } |
使用起来也是很方便的, 只是创建 ViewModel 对象时必须用帮助类来创建实例, 代码如下:
1
2
3
4
5
6
7
8
9
10
|
public class MyViewModel : NotifyPropertyChanged { // 定义属性时不需要任何基类方法, 和普通属性没有什么两样。 public int MyProperty { get ; set ; } } // 使用时需要这样创建实例: var viewModel = ViewModelHelper.CreateProxy<MyViewModel>(); viewModel.MyProperty = 100; |
不过这种实现的缺点就是所有的属性都会触发 PropertyChanged 事件, 而且只能触发一个事件, 而在实际开发中, 偶尔需要设置一个属性, 触发多个 PropertyChanged 事件。
未来 .Net 4.5 的实现方式
在即将发布的 .Net 4.5 中, 提供了 CallerMemberNameAttribute 标记, 利用这个属性, 可以将上面提供的 SetProperty 方法进行改造, 这样的实现才是最完美的:
1
2
3
4
5
6
|
protected void SetProperty<T>( ref T storage, T value, [CallerMemberName] String propertyName = null ) { if ( object .Equals(storage, value)) return ; storage = value; this .OnPropertyChanged(propertyName); } |
由于有了 CallerMemberName 标记助阵, 可以说使用起来是非常方便了:
1
2
3
4
5
6
7
8
9
10
11
|
public class MyViewModel : NotifyPropertyChanged { private int _myField; public int MyProperty { get { return _myField; } set { base .SetProperty( ref _myField, value); } } } |
这种方法虽然好,不过却只有在 .Net 4.5 中才有, 而且也许永远不会添加到 Silverlight 中。
第二步:用户界面绑定数据对象,指定绑定模式
.xaml
<Grid x:Name="LayoutRoot" Background="Wheat" Loaded="LayoutRoot_Loaded">
<StackPanel>
<TextBox Grid.Row="" Grid.Column="" Width="" Height="" HorizontalAlignment="Left" Text="{Binding Name,Mode=OneTime}"/>
<TextBox Grid.Row="" Grid.Column="" Width="" Height="" HorizontalAlignment="Left" Text="{Binding Age,Mode=OneTime}"/>
<TextBox Grid.Row="" Grid.Column="" Width="" Height="" HorizontalAlignment="Left" Text="{Binding Address,Mode=OneTime}"/>
<Button x:Name="btnUpdata" Width="" Height="" Content="更新" Click="btnUpdata_Click"/>
</StackPanel>
</Grid>
第三步:数据绑定
.xaml.cs
Person person;
void LayoutRoot_Loaded(object sender,RoutedEventArgs e)
{
person = new Person()
{
Name="Terry",
Age=,
Address="Beijing"
};
this.LayoutRoot.DataContext = person;
} private void btnUpdata_Click(object sender, RoutedEventArgs e)
{
person.Name = "小哥";
person.Age = ;
person.Address = "上海"; }
由于是OneTime数据绑定模式,可以看出在单机更新按钮时,尽管改变了数据对象的属性值,但是用户界面的数据值依然是在绑定创建时候的数据值。
silverlight简单数据绑定3的更多相关文章
- silverlight简单数据绑定1
数据绑定是用户界面与数据源之间的媒介:通过绑定可以使数据在界面和数据源之间传递交流.数据绑定由System.Windows.Data命名空间的Binding对象完成. 创建绑定的数据对象类. .cs类 ...
- silverlight简单数据绑定2
<Grid x:Name="LayoutRoot" Background="white" Loaded="LayoutRoot_Loaded&q ...
- Silverlight自定义数据绑定控件应该如何处理IEditableObject和IEditableCollectionView对象
原文:Silverlight自定义数据绑定控件应该如何处理IEditableObject和IEditableCollectionView对象 原创文章,如需转载,请注明出处. 最近在一直研究Silve ...
- 【翻译】使用Knockout, Web API 和 ASP.Net Web Forms 进行简单数据绑定
原文地址:http://www.dotnetjalps.com/2013/05/Simple-data-binding-with-Knockout-Web-API-and-ASP-Net-Web-Fo ...
- Knockout, Web API 和 ASP.Net Web Forms 进行简单数据绑定
使用Knockout, Web API 和 ASP.Net Web Forms 进行简单数据绑定 原文地址:http://www.dotnetjalps.com/2013/05/Simple-da ...
- winform中控件的简单数据绑定
是因为在学习组件开发过程中有个Bindable的属性,不明白意义,然后才接触到winform的数据绑定,想着先把数据绑定这块看一下,然后去测试下是否Bindable属性设为false,就不能绑定该属性 ...
- Winform开发常用控件之DataGridView的简单数据绑定——自动绑定
DataGridView控件可谓是Winform开发的重点控件,对于数据的呈现和操作非常方便,DataGridView可谓是既简单又复杂.简单在于其已经集成了很多方法,复杂在于可以使用其实现复杂的数据 ...
- Winform开发常用控件之DataGridView的简单数据绑定——代码绑定DataSet、DataTable、IList、SqlDataReader
前文介绍了Winform为DataGridView提供的数据自动绑定功能,下面介绍一下采用代码的数据绑定 1.用DataSet和DataTable为DataGridView提供数据源 先上代码 pri ...
- DataGrid 简单数据绑定实例1
1.默认数据显示(自动显示列) 后台绑定 //DataGrid 数据绑定 dataGridOne.ItemsSource = _Context.Info.ToList(); 前台定义 <Data ...
随机推荐
- 总结七条助你成为Linux高手的超棒忠告
起初Linux对于我来说其实是很纠结的,因为很早以前就听说过.也曾见各种技术大牛使用过,但是一直觉得非常高深而没有去正式接触.两年前随着自己工作愈发的乏味,又看到了一篇叫做"虽然我是医生,但 ...
- 最小割 总结&&做题记录
模型要点: 1.一般适用于二取一问题或者01规划. 2.利用最小割=最大流,转化为最大流求之. 建议阅读胡伯涛的论文 <<最小割模型在信息学竞赛的应用>>,有精彩有序的证明和各 ...
- DIV+CSS
1.可以引入外部的样式:<link rel="stylesheet" type="text/css" href="外部的CSS文件路径&q ...
- init.sh 学习(转
cd /mnt insmod ss_triger_drv.ko insmod ss_led_alarm_drv.ko insmod ss_img_prc_drv.ko insmod ss_post_i ...
- 关于servlet的filter
Servlet过滤器 2009-12-08 23:12:44| 分类: Java|举报|字号 订阅 一.什么是Servlet过滤器 过滤器是在数据交互之间过滤数据的中间组件,独立于任何平台或 ...
- idea中如何配置tomcat
这几天想通过JDBC驱动使用MySQL数据库,但老是运行不成功,但是写成java就没有问题,于是想到是不是服务器没配置好 idea中配置tomcat的步骤如下 1:File->Settings. ...
- 黑马程序员——【Java基础】——泛型、Utilities工具类、其他对象API
---------- android培训.java培训.期待与您交流! ---------- 一.泛型 (一)泛型概述 1.泛型:JDK1.5版本以后出现的新特性,用于解决安全问题,是一个类型安全机制 ...
- MySQL字符集乱码
学数据库,最让人丧气的就是字符集的问题了,一旦出问题,就会有砸电脑的冲动,特别是在修改很多次字符集后依然不成功的时候! 我用的数据库软件是MySQL 5.1.28.最初出问题的时候,是这样的: 情景一 ...
- 三部曲一(数据结构)-1020-Ultra-QuickSort
通过这道题我大体理解了树状数组的原理和用法,完全用的别人的算法,我把别人算法看懂之后有自己敲了一遍,不得不说这算法真是高深巧妙啊,我开始看都看不懂,还是在别人的讲解下才看懂的,我觉得有必要写个博客记录 ...
- c/c++ 函数指针 指针函数 数组的引用 指针数组 数组指针
1.指针数组数组指针 引用数组 数组的引用 int *a[10] 指针数组 每一个元素都是一个指针 Int (*a)[10] 数组指针 P指向一个含有10个元素的数组 Int (&a)[10] ...