PropertyChanged事件于数据源发生变化时候通知绑定。PropertyChanged事件在数据源发生变化时候通知绑定。

    }   

    textBox1.Text = user.Name;   

            _address = value;   

ObservableCollection

参见http://www.cnblogs.com/beginor/archive/2012/08/13/2636418.html

    User user = new User();    

    private string _address;   

  

    public string Address
  

public Class_Name()   

ObservableCollection

{   

    user.Name = “your name”;    

第一步,创建数据源对象吃Person类实现INotifyPropertyChanged接口,该接口具有PropertyChanged事件,PropertyChanged事件在数据源发生变化时候通知绑定

        get { return _name; }   

        {   

        set    

    {   

当属性改变时,它可通知客户端,并开展界面数据更新.而我们绝不写过多扑朔迷离的代码来更新界面数据,这样可得方法简单而清晰,松耦合和于法易得重新通用.可用的地方最多了:例如上传进度,实时后台数据变动等地方.目前自己发现winform和silverlight都支持,确实是一个强硬的接口.

 

关于INotifyPropertyChanged
 参见http://www.cnblogs.com/beginor/archive/2012/08/13/2636418.html

其的意向:向客户端有某同属于性值已再次改的通。

于Silverlight中创造数据源集合好使用内建的ObservableCollection类,因为ObservableCollection类既实现了INotifyPropertyChanged接口,又实现了INotifyCollectionChanged接口。使用ObservableCollection类不但可以实现Add、Remove、Clear和Insert操作,还可以触发PropertyChanged事件。

列子:

           if(PropertyChanged != null)   

关于INotifyPropertyChanged
 参见http://www.cnblogs.com/beginor/archive/2012/08/13/2636418.html

    public string Name
   

当属性改变时,它可通报客户端,并进行界面数据更新.而我辈毫不写过多犬牙交错的代码来更新界面数据,这样可做到方法简单而清丽,松耦合和吃方换得再通用.可用之地方太多矣:例如上传进度,实时后台数据变动等地方.目前己发觉winform和silverlight都支持,确实是一个强劲的接口.

 

 使用ObservableCollection

    {   

        get { return _address; }   

编一个粗略的业务类

关于 谈谈INotifyPropertyChanged
的实现

  

 

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));
            }
        }

    }

}

}  

}  

    public event PropertyChangedEventHandler PropertyChanged;
   

它们的图:向客户端有某同属于性值已再度改之通。

参见http://www.cnblogs.com/beginor/archive/2012/08/13/2636418.html

.cs

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 表达式来传递属性名称。

                PropertyChanged(this, new PropertyChangedEventArgs(“Name”));   

            _address = value;   

一般的贯彻方式

当时是均等种再普通不了的兑现方式, 代码如下:

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");
      }
   }
}

INotifyPropertyChanged 接口是 WPF/Silverlight 开发中格外关键之接口,
它整合了 ViewModel 的基本功, 数据绑定基本上都亟待以此接口。 所以,
对其的贯彻啊出示甚关键, 下面接贴出己知的几乎栽实现方式,
希望能够打及抛砖引玉的意向。

INotifyPropertyChanged

            }   

            if (PropertyChanged != null)   

            if (PropertyChanged != null)   

        {   

修一个略的业务类

拦方式贯彻

如果对 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 事件。

        set    

 

    textBox2.Text = user.Address;   

        }   

OneTime:仅在数额绑定创建时利用数据源更新目标。

数据源集合对象要连续IEnumerable接口,为了给对象属性和数据源集合的更新(不但包括元素的修改,还连元素的加码及去)保持同步,数据源集合还非得贯彻INotifyPropertyChanged接口和INotifyCollectionChanged接口。

    user.Address = “your address”;    

        }   

        {   

                PropertyChanged(this, new PropertyChangedEventArgs(“Address”));   

  

        set    

public class User : INotifyPropertyChanged   

 

            {   

    }   

    private string _address;   

{   

    public string Name
   

OneTime:仅于数绑定创建时用数据源更新目标。

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));
            }
        }

    }

}

绑定到聚集

    }   

    user.Address = “your address”;    

绑定到聚集

数码绑定的数据源对象足以是一个含有数据的纯粹对象,也足以是一个对象的集。之前,一直当座谈哪边拿对象对象同一个纯对象绑定。Silverlight中之数据绑定还能够以对象对象及聚集对象相绑定,这为是颇常用的。比如显示文章的题材列表、显示平雨后春笋图片等。

相似的兑现方式

当即是一致种植再平凡不了之落实方式, 代码如下:

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");
      }
   }
}

如果一旦绑定到一个会师类型的数据源对象,绑定目标可以动用ItemsControl,如ListBox或DataGrid等。另外,通过定制ItemsControl的数码模板(DataTemplate),还好操纵集合对象中各个一样宗之展示。

        get { return _name; }   

{   

            {   

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 表达式来传递属性名称。

{   

列子:

    public string Address
  

    {   

INotifyPropertyChanged

            }   

}  

    private string _name;
   

 

            {   

    user.Name = “your name”;    

        get { return _address; }   

于构造函数中先绑定

INotifyPropertyChanged 接口是 WPF/Silverlight 开发中好重大的接口,
它结合了 ViewModel 的根基, 数据绑定基本上还待是接口。 所以,
对她的兑现呢显得格外重大, 下面接贴出我晓得的几栽实现方式,
希望能够从至抛砖引玉的意图。

3种多少绑定模式  OneTime(一浅绑定) OneWay(单项绑定) TwoWay(双向绑定)

            {   

    }   

前途 .Net 4.5 的实现方式

于快要揭晓之 .Net 4.5 中,
提供了 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 4.5 中才发生, 而且也许永远不见面补充加至
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数据绑定模式,可以看在单机更新按钮时,尽管改变了数码对象的属于性值,但是用户界面的数据值依然是以绑定创建时候的数据值。

    private string _name;
   

    textBox1.Text = user.Name;   

        set    

 

           if(PropertyChanged != null)   

率先步,创建数据源对象被Person类实现INotifyPropertyChanged接口,该接口具有PropertyChanged事件,PropertyChanged事件在数据源发生变化时候通知绑定

        }   

以构造函数中先绑定

            }   

关于 谈谈INotifyPropertyChanged
的实现

    {   

  

挡方式贯彻

若对 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 事件。

}  

 

            }   

        }   

    User user = new User();    

前途 .Net 4.5 的兑现方式

于将揭晓的 .Net 4.5 中,
提供了 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 4.5 中才发, 而且也许永远不会见补加到
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数据绑定模式,可以看出在单机更新按钮时,尽管改变了数据对象的属性值,但是用户界面的数据值依然是在绑定创建时候的数据值。

3栽多少绑定模式  OneTime(一差绑定) OneWay(单项绑定) TwoWay(双向绑定)

                PropertyChanged(this, new PropertyChangedEventArgs(“Name”));   

    public event PropertyChangedEventHandler PropertyChanged;
   

假设假定绑定到一个集合类型的数据源对象,绑定目标可以以ItemsControl,如ListBox或DataGrid等。另外,通过定制ItemsControl的数模板(DataTemplate),还好控制集合对象被列一样项之亮。

        {   

数据源集合对象要继承IEnumerable接口,为了吃对象属性和数据源集合的换代(不但包括元素的改动,还包元素的增加与去)保持同步,数据源集合还得实现INotifyPropertyChanged接口和INotifyCollectionChanged接口。

public Class_Name()   

            _name = value;   

 使用ObservableCollection

  

    textBox2.Text = user.Address;   

每当Silverlight中创造数据源集合好使内建的ObservableCollection类,因为ObservableCollection类既实现了INotifyPropertyChanged接口,又实现了INotifyCollectionChanged接口。使用ObservableCollection类不但可以实现Add、Remove、Clear和Insert操作,还好触发PropertyChanged事件。

public class User : INotifyPropertyChanged   

                PropertyChanged(this, new PropertyChangedEventArgs(“Address”));   

  

数绑定的数据源对象好是一个暗含数据的单纯对象,也可以是一个目标的聚集。之前,一直在议论什么以对象靶同一个纯净对象绑定。Silverlight中的数目绑定还能拿对象靶及聚集对象相绑定,这吗是很常用的。比如显示文章的题目列表、显示同一多级图片等。

            _name = value;   

.cs