【问题标题】:Strange behaviour on ViewModel property, RaisePropertyChanged not being executedViewModel 属性的奇怪行为,未执行 RaisePropertyChanged
【发布时间】:2011-02-02 21:15:31
【问题描述】:

在将对象添加到 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 以我希望的方式运行的最佳方法是什么?

【问题讨论】:

    标签: c# wpf mvvm mvvm-light


    【解决方案1】:

    当您更改集合时将调用您的 setter,而不是在更改集合的内容时调用。 您需要的是一个通知您更改的集合。查看ObservableCollection&lt;T&gt;-class。注册到其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>(); 
            }
            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.  
    } 
    

    没有设置器的属性
    如果您不需要设置集合,请在创建集合时注册到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>(); 
               _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&lt;string&gt;INotifyCollectionChanged 一起使用更通用。

    【讨论】:

      【解决方案2】:

      当然,它永远不会被调用,因为当您将项目添加到集合时,您实际上并没有设置属性(没有调用 Items 属性的设置器)。

      如果要修改集合,您需要引发一个 CollectionChanged 事件。为此,您需要使用ObservableCollection&lt;T&gt; 而不是通常的List&lt;T&gt;

      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 将相应更新。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-04-10
        • 1970-01-01
        • 2012-02-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多