三种多少绑定形式 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
它的职能:向客户端发出某壹属性值已退换的照料。
当属性更换时,它能够布告客户端,并拓展分界面数据更新.而小编辈决不写过多纵横交叉的代码来更新分界面数据,那样能够成功方法轻便而清丽,松耦合和让艺术变得更通用.可用的地点太多了:比方上传进度,实时后台数据变动等地点.近日本人意识winform和silverlight都帮衬,确实是1个无敌的接口.
在构造函数中先绑定
public Class_Name()
{
User user = new User();
user.Name = “your name”;
user.Address = “your address”;
textBox1.Text = user.Name;
textBox2.Text = user.Address;
}
编写制定几个简练的业务类
public class User : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
if(PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(“Name”));
}
}
}
private string _address;
public string Address
{
get { return _address; }
set
{
_address = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(“Address”));
}
}
}
}
ObservableCollection
绑定到集中
数量绑定的数据源对象能够是三个富含数据的单纯对象,也能够是3个对象的会集。从前,平素在座谈哪边将目的对象与3个纯粹对象绑定。Silverlight中的数据绑定还是能够将对象对象与聚焦对象相绑定,这也是很常用的。举个例子突显文章的问题列表、呈现壹密密麻麻图片等。
设若要绑定到三个集聚类型的数据源对象,绑定指标能够使用ItemsControl,如ListBox或DataGrid等。别的,通过定制ItemsControl的数目模板(DataTemplate),仍是能够调控集结对象中各种的体现。
使用ObservableCollection
数据源集结对象必须三番五次IEnumerable接口,为了让对象属性与数据源集合的翻新(不但包含成分的更换,还包蕴成分的加码和删除)保持同步,数据源集结还非得兑现INotifyPropertyChanged接口和INotifyCollectionChanged接口。
在Silverlight中开创数据源集合能够应用内建的ObservableCollection类,因为ObservableCollection类既贯彻了INotifyPropertyChanged接口,又完毕了INotifyCollectionChanged接口。使用ObservableCollection类不但能够兑现Add、Remove、Clear和Insert操作,还足以触发PropertyChanged事件。
关于 谈谈INotifyPropertyChanged
的实现
参见http://www.cnblogs.com/beginor/archive/2012/08/13/2636418.html
INotifyPropertyChanged 接口是 WPF/Silverlight 开拓中相当首要的接口,
它构成了 ViewModel 的底子, 数据绑定基本上都亟待以此接口。 所以,
对它的实现也呈现煞是主要, 下边接贴出自己明白的二种达成格局,
希望能起到一得之见的功能。
貌似的兑现格局
那是1种再常见不过的达成方式, 代码如下:
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 事件,
而且只好触发2个风云, 而在实质上支付中, 有的时候供给设置贰脾性能, 触发三个PropertyChanged 事件。
前程 .Net 肆.五 的落到实处情势
在将在公布的 .Net 四.伍 中,
提供了 CallerMemberNameAttribute.aspx) 标识,
利用这脾天性, 能够将地方提供的 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 四.五 中才有, 而且恐怕永久不会增多到
Silverlight 中。
其次步:用户分界面绑定数据对象,钦点绑定格局
.xaml
<Grid x:Name="LayoutRoot" Background="Wheat" Loaded="LayoutRoot_Loaded">
<StackPanel>
<TextBox Grid.Row="0" Grid.Column="0" Width="150" Height="30" HorizontalAlignment="Left" Text="{Binding Name,Mode=OneTime}"/>
<TextBox Grid.Row="1" Grid.Column="0" Width="150" Height="30" HorizontalAlignment="Left" Text="{Binding Age,Mode=OneTime}"/>
<TextBox Grid.Row="2" Grid.Column="0" Width="150" Height="30" HorizontalAlignment="Left" Text="{Binding Address,Mode=OneTime}"/>
<Button x:Name="btnUpdata" Width="150" Height="30" Content="更新" Click="btnUpdata_Click"/>
</StackPanel>
</Grid>
其三步:数据绑定
.xaml.cs
Person person;
void LayoutRoot_Loaded(object sender,RoutedEventArgs e)
{
person = new Person()
{
Name="Terry",
Age=20,
Address="Beijing"
};
this.LayoutRoot.DataContext = person;
}
private void btnUpdata_Click(object sender, RoutedEventArgs e)
{
person.Name = "小哥";
person.Age = 23;
person.Address = "上海";
}
由于是OneTime数据绑定方式,能够看到在单机更新按键时,就算改造了数码对象的属性值,不过用户分界面包车型地铁数据值照旧是在绑定成立时候的数据值。