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 ...
随机推荐
- plist
<a title="iphone" href="itms-services://?action=download-manifest&url=https:// ...
- linux maven安装配置
1.Run the wget command from the dir you want to extract maven too. wget http://mirrors.cnnic.cn/apac ...
- Android中的五大布局
Android中的五大布局 1.了解布局 一个丰富的界面总是要由很多个控件组成的,那我们如何才能让各个控件都有条不紊地 摆放在界面上,而不是乱糟糟的呢?这就需要借助布局来实现了.布局是一种可用于放置很 ...
- 关于javascript中的===和==
=是赋值符号,==是等于,===是严格等于. 对于等号两边的数值,如果类型不相同会先转换类型再比较,===则不会转换类型. 例如3和“3”在==比较下true,在===下是false, null和un ...
- Web页中table导出到execl(带模板)
1.将excel另存为html,将其复制到aspx文件中 2.输出格式为excel InitData(); Response.Clear(); Response.Buffer = true; Resp ...
- JS运动基础(三) 弹性运动
加减速运动速度不断增加或减少速度减小到负值,会向反方向运动 弹性运动在目标点左边,加速:在目标点右边,减速根据距离,计算加速度 带摩擦力的弹性运动弹性运动+摩擦力 弹性:速度 += (目标点 - 当前 ...
- iTunesConnect进行App转移2-官方说明
Can I transfer an app to another developer's iTunes Connect account? Yes, you can transfer your app ...
- 关于配置服务器(IIS7)(二)
然 ,你以为这样就解决问题了? 图样 图森破(too yong too simply).......... HTTP 错误 500.21 - Internal Server Error 处理程序“Pa ...
- ajax 中$.each(json,function(index,item){ }); 中的2个参数表示什么意思?
$.each(json,function(index,item)里面的index代表当前循环到第几个索引,item表示遍历后的当前对象,比如json数据为:[{"name":&qu ...
- QString转换为char* (转)
Qt下面,字符串都用QString,确实给开发者提供了方便,想想VC里面定义的各种变量类型,而且函数参数类型五花八门,经常需要今年新那个类型转换 Qt再使用第三方开源库时,由于库的类型基本上都是标准的 ...