【问题标题】:MVVM ObservableCollection Bind TwoWayMVVM ObservableCollection 双向绑定
【发布时间】:2012-02-10 08:35:53
【问题描述】:

我一直在使用 MVVM,想知道如何使用 ObservableCollection 在 TwoWay 中绑定到 ItemsSource?

例如,我有一个名为 SmartDraw 的自定义绘图用户控件,其中 ItemsSource 引用自定义图形列表,它绑定到视图模型中的 ObservableCollection 图形。

如果我在视图模型中添加一个CustomGraphic,SmartDraw中的ItemsSource就会知道有一个CustomGraphic的添加,然后做一些其他的函数调用。这是正常的。

然而,SmartDraw 也是一个 Canvas,它允许用户使用鼠标在其上绘制图形。 CustomGraphic 的数量会根据用户的绘图而改变。那么,我怎么知道 UI(SmartDraw) 改变了 ObservableCollection?

这是我的代码:

视图模型:

public ObservableCollection<CustomGraphic> Graphics { get; set; }

非常感谢。

【问题讨论】:

  • 您能否添加一些有关用户控件的更多信息。目前尚不清楚是否有事件可让您跟踪何时因用户操作而添加了 CustomGraphic 项。
  • 在 ObservableCollection 的双向绑定中,我怎么知道 ViewModel 中的集合发生了变化?
  • 查看分析器...但是我不确定这是您要的。

标签: mvvm observablecollection


【解决方案1】:

不确定这是否能回答您的问题……但一般来说,这是您如何跟踪可观察集合的更改。

要检测对可观察集合的更改(而不是对集合中项目属性的更改),您订阅ObservableCollection 的CollectionChanged 事件。

private ObservableCollection<ViewModel> _collection;
public ObservableCollection<ViewModel> Collection {
    get { return _collection; }
    set {
        if (_collection != value) {
            // de-register on collection changed
            if (_collection != null)
                _collection.CollectionChanged -= this.Collection_CollectionChanged;

            _collection = value;

            // re-register on collection changed
            if (_collection != null)
                _collection.CollectionChanged += this.Collection_CollectionChanged;
    }
}

private void Collection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
    switch (e.Action) {
    case NotifyCollectionChangedAction.Add:
            // e.NewItems contains the added items
    break;
    case NotifyCollectionChangedAction.Remove:
            // e.OldItems contains the removed items
            break;
        case NotifyCollectionChangedAction.Replace:
            // e.NewItems contains the new items, 
            // e.OldItems contains the removed items
            break;
        case NotifyCollectionChangedAction.Reset:
            // the collection has been cleared
            break;
    }
}

如果您需要跟踪集合中对象的更改,您必须构建一个扩展的 ObservableCollection 订阅项目的 PropertyChanged 事件,然后在这些属性之一发生更改时引发事件。

public class ObservableCollectionEx<TValue> : ObservableCollectionAddRange<TValue>
{

   public ObservableCollectionEx() : base() { }
   public ObservableCollectionEx(IEnumerable<TValue> values)
      : base(values)
   {
      this.EnsureEventWiring();
   }
   public ObservableCollectionEx(List<TValue> list)
      : base(list)
   {
      this.EnsureEventWiring();
   }

   public event EventHandler<ItemChangedEventArgs> ItemChanged;

   protected override void InsertItem(int index, TValue item)
   {
      base.InsertItem(index, item);

      var npc = item as INotifyPropertyChanged;
      if (npc != null)
         npc.PropertyChanged += this.HandleItemPropertyChanged;
   }

   protected override void RemoveItem(int index)
   {
      var item = this[index];

      base.RemoveItem(index);

      var npc = item as INotifyPropertyChanged;
      if (npc != null)
         npc.PropertyChanged -= this.HandleItemPropertyChanged;
   }

   protected override void SetItem(int index, TValue item)
   {
      var oldItem = this[index];

      base.SetItem(index, item);

      var npcOld = item as INotifyPropertyChanged;
      if (npcOld != null)
         npcOld.PropertyChanged -= this.HandleItemPropertyChanged;

      var npcNew = item as INotifyPropertyChanged;
      if (npcNew != null)
         npcNew.PropertyChanged += this.HandleItemPropertyChanged;
   }

   protected override void ClearItems()
   {
      var items = this.Items.ToList();

      base.ClearItems();

      foreach (var npc in items.OfType<INotifyPropertyChanged>().Cast<INotifyPropertyChanged>())
         npc.PropertyChanged -= this.HandleItemPropertyChanged;
   }


   private void HandleItemPropertyChanged(object sender, PropertyChangedEventArgs args)
   {
      if (typeof(TValue).IsAssignableFrom(sender.GetType()))
      {
         var item = (TValue)sender;
         var pos = this.IndexOf(item);
         this.OnItemChanged(item, pos, args.PropertyName);
      }
   }

   protected virtual void OnItemChanged(TValue item, int index, string propertyName)
   {
      if (this.ItemChanged != null)
         this.ItemChanged(this, new ItemChangedEventArgs(item, index, propertyName));
   }

   private void EnsureEventWiring()
   {
      foreach (var npc in this.Items.OfType<INotifyPropertyChanged>().Cast<INotifyPropertyChanged>())
      {
         npc.PropertyChanged -= this.HandleItemPropertyChanged;
         npc.PropertyChanged += this.HandleItemPropertyChanged;
      }
   }

   public class ItemChangedEventArgs : EventArgs
   {
      public ItemChangedEventArgs(TValue item, int index, string propertyName)
      {
         this.Item = item;
         this.Index = index;
         this.PropertyName = propertyName;
      }

      public int Index { get; private set; }
      public TValue Item { get; private set; }
      public string PropertyName { get; private set; }
   }
}

【讨论】:

    猜你喜欢
    • 2020-12-04
    • 2011-08-27
    • 2013-09-18
    • 2014-02-14
    • 1970-01-01
    • 2018-07-27
    • 1970-01-01
    • 2016-08-05
    • 1970-01-01
    相关资源
    最近更新 更多