Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I'm posting my workaround - which is a custom class - here. Still hoping for better answers.</p> <pre><code>using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Linq; namespace ViewLayer { public class TransformObservableCollection&lt;T,Source&gt; : INotifyCollectionChanged, IList, IReadOnlyList&lt;T&gt;, IDisposable { public TransformObservableCollection(ObservableCollection&lt;Source&gt; wrappedCollection, Func&lt;Source,T&gt; transform) { m_WrappedCollection = wrappedCollection; m_TransformFunc = transform; ((INotifyCollectionChanged)m_WrappedCollection).CollectionChanged += TransformObservableCollection_CollectionChanged; m_TransformedCollection = new ObservableCollection&lt;T&gt;(m_WrappedCollection.Select(m_TransformFunc)); } public void Dispose() { if (m_WrappedCollection == null) return; ((INotifyCollectionChanged)m_WrappedCollection).CollectionChanged -= TransformObservableCollection_CollectionChanged; m_WrappedCollection = null; } void TransformObservableCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { switch (e.Action) { case NotifyCollectionChangedAction.Add: if (e.NewItems == null || e.NewItems.Count != 1) break; m_TransformedCollection.Insert(e.NewStartingIndex,m_TransformFunc((Source)e.NewItems[0])); return; case NotifyCollectionChangedAction.Move: if (e.NewItems == null || e.NewItems.Count != 1 || e.OldItems == null || e.OldItems.Count != 1) break; m_TransformedCollection.Move(e.OldStartingIndex, e.NewStartingIndex); return; case NotifyCollectionChangedAction.Remove: if (e.OldItems == null || e.OldItems.Count != 1) break; m_TransformedCollection.RemoveAt(e.OldStartingIndex); return; case NotifyCollectionChangedAction.Replace: if (e.NewItems == null || e.NewItems.Count != 1 || e.OldItems == null || e.OldItems.Count != 1 || e.OldStartingIndex != e.NewStartingIndex) break; m_TransformedCollection[e.OldStartingIndex] = m_TransformFunc((Source)e.NewItems[0]); return; } // This is most likely called on a Clear(), we don't optimize the other cases (yet) m_TransformedCollection.Clear(); foreach (var item in m_WrappedCollection) m_TransformedCollection.Add(m_TransformFunc(item)); } #region IList Edit functions that are unsupported because this collection is read only public int Add(object value) { throw new InvalidOperationException(); } public void Clear() { throw new InvalidOperationException(); } public void Insert(int index, object value) { throw new InvalidOperationException(); } public void Remove(object value) { throw new InvalidOperationException(); } public void RemoveAt(int index) { throw new InvalidOperationException(); } #endregion IList Edit functions that are unsupported because this collection is read only #region Accessors public T this[int index] { get { return m_TransformedCollection[index]; } } object IList.this[int index] { get { return m_TransformedCollection[index]; } set { throw new InvalidOperationException(); } } public bool Contains(T value) { return m_TransformedCollection.Contains(value); } bool IList.Contains(object value) { return ((IList)m_TransformedCollection).Contains(value); } public int IndexOf(T value) { return m_TransformedCollection.IndexOf(value); } int IList.IndexOf(object value) { return ((IList)m_TransformedCollection).IndexOf(value); } public int Count { get { return m_TransformedCollection.Count; } } public IEnumerator&lt;T&gt; GetEnumerator() { return m_TransformedCollection.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)m_TransformedCollection).GetEnumerator(); } #endregion Accessors public bool IsFixedSize { get { return false; } } public bool IsReadOnly { get { return true; } } public void CopyTo(Array array, int index) { ((IList)m_TransformedCollection).CopyTo(array, index); } public void CopyTo(T[] array, int index) { m_TransformedCollection.CopyTo(array, index); } public bool IsSynchronized { get { return false; } } public object SyncRoot { get { return m_TransformedCollection; } } ObservableCollection&lt;T&gt; m_TransformedCollection; ObservableCollection&lt;Source&gt; m_WrappedCollection; Func&lt;Source, T&gt; m_TransformFunc; event NotifyCollectionChangedEventHandler INotifyCollectionChanged.CollectionChanged { add { ((INotifyCollectionChanged)m_TransformedCollection).CollectionChanged += value; } remove { ((INotifyCollectionChanged)m_TransformedCollection).CollectionChanged -= value; } } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload