ViewModel属性上的奇怪行为,RaisePropertyChanged未被执行

时间:2011-02-02 21:15:31

标签: c# wpf mvvm mvvm-light

我注意到在向ViewModel属性添加对象时,RaisePropertyChanged会出现奇怪的行为。

private List<string> _items;
public List<string> Items
{
    get 
    {
        if(_items == null){ _items = new List<string>(); } 
        return _itmes; 
    }
    set
    {
        _items = value;
        RaisePropertyChanged("Items");
    }
}

我什么时候通过属性

将对象添加到集合中
Items.Add("new string");

永远不会调用RaisePropertyChanged。

让RaisePropertyChanged按照我希望的方式运行的最佳方法是什么?

2 个答案:

答案 0 :(得分:5)

更改集合时将调用您的setter,而不是在更改集合的内容时调用。 您需要的是一个通知您变化的集合。看看ObservableCollection<T> - 班级。注册参加CollectionChanged活动,了解变更情况。

带有二传手的属性
以下示例显示如何使用包含可观察集合的可设置属性。该示例的复杂性是因为可以从实例的外部设置集合。如果您不需要此功能,解决方案将变得更加简单。

private ObservableCollection<string> _items;
public ObservableCollection<string> Items {
    get {
        if (_items == null) { 
           // Create a new collection and subscribe to the event
           Items=new ObservableCollection<string>(); 
        }
        return _items;
    }
    set {
      if(value !=_items){
        if (null != _items) {
            // unsubscribe for the old collection
            _items.CollectionChanged -= new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_items_CollectionChanged);
        }
        _items = value;
        if (null != _items) {
            // subscribe for the new collection
            _items.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_items_CollectionChanged);    
        }
        // Here you will be informed, when the collection itselfs has been changed
        RaisePropertyChanged("Items");
    }
  }
}

void _items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) {
    // Here you will be informed, if the content of the collection has been changed.  
} 

没有二传手的属性
如果您不需要将集合设置为setable,请在创建集合时注册CollectionChanged。但是,您必须删除属性的setter。如果收集已更改,则不会通知更改:

private ObservableCollection<string> _items; 
public ObservableCollection<string> Items {
    get {
        if (_items == null) { 
           // Create a new collection and subscribe to the event
           _items=new ObservableCollection<string>(); 
           _items.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler
        }
        return _items;
    }
}

void _items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) {
    // Here you will be informed, if the content of the collection has been changed.  
} 

其他信息
有关集合更改的更多信息,请查看INotifyCollectionChanged 。以上示例您还可以使用IEnumerable<string>INotifyCollectionChanged更加通用。

答案 1 :(得分:2)

当然,它永远不会被调用,因为当您向集合中添加项目时,实际上并未设置属性(未调用Items属性的setter)。

如果是集合修改,您需要的是引发CollectionChanged事件。为此,您需要使用ObservableCollection<T>而不是通常List<T>

private ObservableCollection<string> _items;
public ObservableCollection<string> Items
{
    get 
    {
        if(_items == null){ _items = new ObservableCollection<string>(); } 
        return _itmes; 
    }
    set
    {
        _items = value;
        RaisePropertyChanged("Items");
    }
}

现在,当您向集合添加项目时,将引发CollectionChanged事件,并且您的UI将相应地更新。