2012-03-07 78 views
0

我有一个由三个类组成的模型:A,B和C. A具有B的ObservableCollection,B具有C的ObservableCollection。 C具有引用(不可观察..我不认为是必要的)给它的父母(B),并且B有一个对A的引用。 A,B和C的每个属性通知它的变化。通知属性不在UI中“更新”

然后我有一个Model类,它可以“跟踪”分配的所有对象。所以它有一个A,B和C的ObservableCollection(唯一需要的是As;我保留B和C的列表仅用于更快的引用)。

我的用户界面有一个自定义控件:它有一个ViewModel。该视图有一个列表。它的ItemSources绑定到它的ViewModel到一个名为sensors的observablecollection。这个ObservableCollection是RowViewModel的。每个RowViewModel保持对C对象的引用。

我的应用程序加载模型(创建A,B,C的对象),然后通过调用此方法设置视图列表(也许这是什么问题?)

public void setSensors(IList<C> list) 
     { 
      this.sensors.Clear(); 
      if (list != null) 
      { 
       foreach (var row in list) 
        this.sensors.Add(new RowViewModel(row)); 
      } 
     } 

的问题是,如果我修改了我的C对象的属性,这不反映在用户界面上。

有人可以帮助我吗? 谢谢

弗朗西斯

编辑:(解决) 感谢您的回答我检查了我的代码,改变了一两件事:不是我的UI元素绑定到它的视图模型(以及视图模型只是“重定向”的号召到模型属性),我直接将用户界面绑定到不动产,并且它可以工作! 因此......在MVVM中,我不能使用“快捷方式”??或者如果我使用它们,我应该注册属性的通知并“传播”它们?

+0

你的财产更改了正确触发的事件吗? – squelos 2012-03-07 08:45:33

+0

呃..我想是的。我在我的“NotifyPropertyChanged”中放置了一个断点,然后输入它 – Francesco 2012-03-07 08:47:09

+0

尝试检查是否有人正在收听这些事件。如果正确的对象正在有效地收听,那么我不知道:/ – squelos 2012-03-07 08:49:56

回答

1

我认为你的UI没有更新,因为它被绑定到RowViewModel对象,而不是C。因此,您应在RowViewModel的构造函数中订阅PropertyChanged事件C,并通过RowViewModel.PropertyChanged通知有关更改。顺便说一句,你能提供一个绑定在你的用户界面的例子吗?

更新:

“代理” PropertyChanged事件的一个例子:

public class Model: INotifyPropertyChanged 
{ 
    private string _YourProperty; 
    public string YourProperty 
    { 
    get { return _YourProperty; } 
    set 
    { 
     if (_YourProperty == value) return; 
     _YourProperty = value; 
     RaisePropertyChanged("YourProperty"); 
    } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void RaisePropertyChanged(string propertyName) 
    { 
    if (PropertyChanged != null) 
     PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

public class ViewModel: INotifyPropertyChanged 
{ 
    private Model _Model; 

    public ViewModel(Model model) 
    { 
    _Model = model; 
    _Model.PropertyChanged += OnModelPropertyChanged; 
    } 

    public string YourProperty 
    { 
    get { return _Model.YourProperty; } 
    } 

    private void OnModelPropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
    if (e.PropertyName == "YourProperty") 
     RaisePropertyChanged("YourProperty"); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void RaisePropertyChanged(string propertyName) 
    { 
    if (PropertyChanged != null) 
     PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

您也可以http://george.softumus.com/2011/10/inotifypropertychanged-and-magic.html阅读 - 如何避免使用 “魔术字符串”(硬编码常量)作为属性名称。

+0

我没有声望添加答案..所以...我的行用户界面是这样做的: isOnline属性在RowViewModel中: public Boolean isOnline { get { return myC.baisOnline; } } 我的疑问是... b和属性不是“可观察的”,但在线是。 – Francesco 2012-03-07 08:48:59

+0

我没有看到任何需要代理属性更改事件的所有广告您的属性在构造函数中设置。并没有改变。这实际上并不是必要的,它更危险,每次更新视图模型的模型时,模型的属性都会发生变化,这将导致Silverlight无故刷新所有内容。 – 2012-03-07 18:50:34

+0

好的,非常简单的例子 - 你有模型有2个属性,比如'Name'和'Version',并且想在你的视图中看到它为' [v。 ]'(例如'SuperTool [v.2]')。代理属性是一种简单的方法(在WPF中可以使用'IMultiValueConverter',但Silvelight没有它)。实际上还有很多其他的例子,当你想使用代理。当然,几乎总是可以使用其他技术。但是这个问题非常棘手,每个特定场景中最好的方法是什么。所以最好知道代理存在,这是你自己的选择 - 使用它或不。 – chopikadze 2012-03-11 06:02:15

1

规则模型自动更新的用户界面: -

  1. 你Collection类型的物业类型必须的ObservableCollection
  2. 模型应实现INotifyPropertyChanged接口
  3. 模型的每个属性,除非它是字符串或值类型,必须实现INotifyPropertyChanged的类型
  4. 如果您的值类型集合的Property属性发生更改,则应为属性名称触发PropertyChanged,即使它是从ObservableColle派生的ction
+0

我认为我遵循这个规则... – Francesco 2012-03-07 08:53:42

+0

最有可能的第四条规则不是跟在人后面,因为他们认为集合实例的更改与集合中的添加/删除项目相同,否则您将不得不检查VS中的绑定警告输出窗口。 – 2012-03-07 08:56:51