MVVM ObservableCollection Bind TwoWay - PullRequest
       0

MVVM ObservableCollection Bind TwoWay

0 голосов
/ 10 февраля 2012

Я работал с MVVM и спрашивал себя, как использовать ObservableCollection для привязки к ItemsSource в TwoWay?

Например, у меня есть пользовательский чертеж UserControl под названием SmartDraw, в котором ItemsSource ссылается насписок пользовательских графических объектов, и он привязан к графическому объекту ObservableCollection в модели представления.

Если я добавлю CustomGraphic в модель представления, ItemsSource в SmartDraw будет знать, что существует добавление CustomGraphic, а затем выполнит командунекоторые другие вызовы функций.Это нормально.

Однако SmartDraw также является Canvas, который позволяет пользователю рисовать на нем графику с помощью мыши.Количество CustomGraphic будет меняться в зависимости от пользовательского рисунка.Итак, как я мог знать, что ObservableCollection изменен пользовательским интерфейсом (SmartDraw)?

Вот мой код:

ViewModel:

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

Большое спасибо.

1 Ответ

0 голосов
/ 16 февраля 2012

Не уверен, отвечает ли это на ваш вопрос ... но вот как вы будете отслеживать изменения в наблюдаемой коллекции в целом.

Чтобы обнаружить изменения в наблюдаемой коллекции (не изменения в свойствах элементов внутриколлекции) вы подписываетесь на событие CollectionChanged 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, которая подписывается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; }
   }
}
...