MVVM ObservableCollection绑定双向 [英] MVVM ObservableCollection Bind TwoWay

查看:116
本文介绍了MVVM ObservableCollection绑定双向的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have been working with MVVM and wondering how to make use of ObservableCollection to bind to an ItemsSource in TwoWay?

例如,我有一个名为SmartDraw的自定义工程图用户控件,其中ItemsSource引用了自定义图形"列表,并绑定到视图模型中的ObservableCollection图形.

For example, I have an Custom Drawing UserControl called SmartDraw, in which the ItemsSource refers to the list of Custom Graphics and it is bound to an ObservableCollection Graphics in the View Model.

如果我在视图模型中添加CustomGraphic,则SmartDraw中的ItemsSource会知道还有CustomGraphic的添加,然后执行其他一些函数调用.是正常的.

If I add a CustomGraphic in the view model, the ItemsSource in the SmartDraw will know that there is an addition of CustomGraphic and then do some other function calls. It is normal.

但是,SmartDraw还是Canvas,使用户可以使用鼠标在其上绘制图形. CustomGraphic的数量将根据用户图纸而改变.那么,我怎么知道UI(SmartDraw)改变了ObservableCollection?

However, the SmartDraw is also a Canvas which enable user to draw graphics on it using mouse. The number of CustomGraphic will change according to the user drawing. So, how could I know the ObservableCollection is changed by the UI(SmartDraw)?

这是我的代码:

ViewModel:

ViewModel:

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

非常感谢您.

推荐答案

不确定是否能回答您的问题...但是这里是您通常如何跟踪对可观察集合的更改.

Not sure whether this answers your question ... but here is how you would track changes to an observable collection in general.

要检测对可观察集合的更改(而不是对集合内项目的属性的更改),请订阅ObservableCollectionCollectionChanged事件.

To detect changes to an observable collection (not changes to properties of the items within the collection) you subscribe to the CollectionChanged event of the ObservableCollection.

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,该扩展ObservableCollection订阅项目的PropertyChanged事件,然后在这些属性之一发生更改时引发一个事件.

If you need to track changes to the objects within the collection you have to build a extended ObservableCollection that subscribes to the PropertyChanged events of the items and then raises an event if one of these properties has changed.

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; }
   }
}

这篇关于MVVM ObservableCollection绑定双向的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆