2012-02-10 4 views
0

MVVM을 사용하여 ObservableCollection 을 TwoWay의 ItemsSource에 바인딩하는 방법을 궁금해했습니다.MVVM ObservableCollection Between TwoWay

예를 들어, ItemsSource가 사용자 지정 그래픽 목록을 참조하고보기 모델의 ObservableCollection Graphics에 바인딩 된 SmartDraw라는 사용자 지정 그리기 UserControl이 있습니다.

뷰 모델에 CustomGraphic을 추가하면 SmartDraw의 ItemsSource에 CustomGraphic이 추가 된 것을 알게되고 다른 함수 호출이 수행됩니다. 보통이다.

그러나 SmartDraw는 사용자가 마우스로 그래픽을 그릴 수있는 Canvas이기도합니다. CustomGraphic의 수는 사용자 도면에 따라 변경됩니다. 그렇다면 ObservableCollection이 UI (SmartDraw)에 의해 변경된다는 것을 어떻게 알 수 있습니까?

뷰 모델 :

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

너무 감사

여기 내 코드입니다.

+0

사용자 정의 컨트롤에 대한 정보를 추가 할 수 있습니까? 사용자 작업으로 인해 CustomGraphic 항목이 추가 될 때 추적 할 수있는 이벤트가 있는지 여부는 분명하지 않습니다. – AxelEckenberger

+0

ObservableCollection <>의 양방향 바인딩에서 ViewModel에서 컬렉션이 변경된 것을 어떻게 알 수 있습니까? – user1184598

+0

anser를 보아라. 그러나 나는 이것이 당신이 요구하고있는 것이 확실하지 않다. – AxelEckenberger

답변

0

이 질문에 대한 답변 여부는 확실하지 않지만 다음은 관찰 가능한 컬렉션의 변경 사항을 추적하는 일반적인 방법입니다.

관찰 가능한 컬렉션의 변경 사항 (컬렉션 내의 항목 속성 변경되지 않음)을 확인하려면 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; 
    } 
} 

당신이 항목의 PropertyChanged 이벤트를 구독하고 이러한 속성 중 하나가 변경된 경우 이벤트를 발생시키는 확장 ObservableCollection을 구축해야 컬렉션 내의 객체에 대한 변경 사항을 추적해야합니다.

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; } 
    } 
} 
관련 문제