2010-08-24 90 views
11

所有使用MVVM的Silverlight示例都使用名为IPropertyChanged的接口。它背后的概念是什么?为什么每当我们设定一些价值时就需要举办一个活动?INotifyPropertyChanged背后的概念是什么?

如: -

public class UserNPC:INotifyPropertyChanged 
{ 
    private string name; 
    public string Name { 
     get { return name; } 
     set { name = value; onPropertyChanged(this, "Name"); } 
    } 
    public int grade; 
    public int Grade { 
     get { return grade; } 
     set { grade = value; onPropertyChanged(this, "Grade"); } 
    } 

    // Declare the PropertyChanged event 
    public event PropertyChangedEventHandler PropertyChanged; 

    // OnPropertyChanged will raise the PropertyChanged event passing the 
    // source property that is being updated. 
    private void onPropertyChanged(object sender, string propertyName) 
    { 
     if (this.PropertyChanged != null) 
     { 
      PropertyChanged(sender, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

什么是INotifyPropertyChanged的确切目的是什么?

回答

15

您有以下依赖性:

查看→装订→型号

现在,这个概念是如下:

如果您型号对象改变了一些数据,您需要提高PropertyChanged事件。为什么?因为Binding对象已经用数据对象的PropertyChanged事件注册了一个方法。

因此,当您的模型对象发生变化时,您需要做的就是提升事件并完成。

当你这样做,绑定对象得到通知你的事件发生的变化。 绑定对象反过来让对象知道发生了某些事情。查看对象然后可以根据需要更新UI。

代码示例

这里有一个编译例子。设置几个断点,通过F11逐步完成代码并查看幕后发生的情况。请注意,此示例具有以下依赖关系:View→Model。我遗漏了绑定对象。

using System; 
using System.ComponentModel; 

namespace INotifyPropertyChangedDemo 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      // Create 2 listeners. 
      View1 view1 = new View1(); 
      View2 view2 = new View2(); 

      // Create 1 data object. 
      Model model = new Model(); 

      // Connect listener with data object. 
      model.PropertyChanged += new PropertyChangedEventHandler(view1.MyPropertyChangedEventHandler); 
      model.PropertyChanged += new PropertyChangedEventHandler(view2.MyPropertyChangedEventHandler); 

      // Let data object publish change notification. 
      model.FirstName = "new name"; 

      // Check whether all listeners got notified. 
      // ... via console. 
     } 

     public class Model : INotifyPropertyChanged 
     { 
      public event PropertyChangedEventHandler PropertyChanged; 

      private string firstName; 
      public string FirstName 
      { 
       get { return firstName; } 
       set 
       { 
        if (firstName != value) 
        { 
         firstName = value; 
         if (PropertyChanged != null) 
         { 
          PropertyChanged(this, new PropertyChangedEventArgs("FirstName")); 
         } 
        } 
       } 
      } 
     } 

     public class View1 
     { 
      public void MyPropertyChangedEventHandler(object source, PropertyChangedEventArgs arg) 
      { 
       Console.WriteLine("Listener 1: Changed Property: {0}", arg.PropertyName); 
       string newValue = ((Model) source).FirstName; 
       Console.WriteLine("Listener 1: Changed Property Value: {0}", newValue); 
      } 
     } 

     public class View2 
     { 
      public void MyPropertyChangedEventHandler(object source, PropertyChangedEventArgs arg) 
      { 
       Console.WriteLine("Listener 2: Changed Property: {0}", arg.PropertyName); 
       string newValue = ((Model)source).FirstName; 
       Console.WriteLine("Listener 2: Changed Property Value: {0}", newValue); 
      } 
     } 
    } 
} 
3

大多数Silverlight控件通过订阅PropertyChanged事件来监听它们显示的数据更改。

例如控制确实是这样的幕后:

public void Loaded() 
    { 
     if (myDataObject is INotifyPropertyChanged) 
     { 
      (myDataObject as INotifyPropertyChanged).PropertyChanged +=new PropertyChangedEventHandler(onPropertyChanged); 
     } 
    } 

这也是为什么的ObservableCollection是用来代替在Silverlight应用程序更简单的列表。它们实现INotifyPropertyChanged,以便显示集合的控件能够查看列表中发生的更改以及列表中的单个项目。

5

WPF中的MVVM & Silverlight通过将UI元素绑定到视图模型来实现。但是,当视图模型发生变化时,界面知道如何更新自身?

INotifyPropertyChanged只是暴露了UI可以“侦听”的事件,因此当控件“听到”绑定到的属性发生了变化时,它可以“自行更新”。

例如,假设您有一个显示股票价格的TextBlock,并且它绑定到视图模型的string Price属性。视图模型反过来使用服务每30秒更新一次股票价格。因此,每30秒Price属性发生变化:30秒前它是“29.20美元”,现在是“29.12美元”,从现在开始30秒将是“28.10美元”。当加载TextBlock时应用TextBlock绑定,但在每次Price更改时都不会应用该绑定。但是,如果您实施INotifyPropertyChanged并在Price设置人员中提升了“物业价格”事件,则TextBlock可以连线到事件中,从而“知道”何时返回并“重读”Price财产并更新显示的文字。

0

我创造了一个3层的计划最近的乐趣,并希望确保所有地方的分离尽可能部分。

在我的GUI中,用户可以键入一个名称,但他们想要的,但是,我的商务类有逻辑在那里将所有名称更改为Title Case。然而,这种方式很有效,但从未告知图形用户界面从未被告知该业务类所做的更新。

所以我当时的工作很简单......但看起来不正确。类似以下内容

var _person = new Person(); 

// In some form event handler like button click 
_person.Name = txtName.Text; 
txt.Name.Text = _person.Name; 

这样做的目的是更新GUI,同时保持它与业务逻辑分开。我想要的是创建一个事件,当业务逻辑改变GUI中键入的值时GUI会触发该事件并触发该事件。

所以现在我会像...

var _person = new Person(); 

// In some form event handler like button click 
_person.Name = txtName.Text; 


// In the GUI class 
public void OnInternalPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs) 
{ 
    txtName.Text = _person.Name; 
} 

注:我没有做这所有的属性更改......刚刚从什么用户希望它是偏离的那些...将所有小写名称更改为Title Case,并将其显示给用户。