2012-02-10 26 views
0

MVVMで作業していて、ObservableCollection をTwoWayのItemsSourceにバインドする方法を知りましたか?MVVM ObservableCollectionバインドTwoWay

たとえば、SmartDrawというCustom Drawing UserControlがあります。その中には、ItemsSourceがカスタムグラフィックスのリストを参照し、View ModelのObservableCollection Graphicsにバインドされています。

ビューモデルにCustomGraphicを追加した場合、SmartDrawのItemsSourceはCustomGraphicの追加があることを知り、他の関数呼び出しを行います。それは正常です。

しかし、SmartDrawは、ユーザーがマウスを使用して画像を描画できるCanvasです。 CustomGraphicの数は、ユーザーの図面に応じて変更されます。では、ObservableCollectionがUI(SmartDraw)によって変更されたことはどうすればわかりますか?ここで

は私のコードです:

のViewModel:

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; } 
    } 
} 
関連する問題