How can I make a read-only ObservableCollection property?

前端 未结 5 1617
你的背包
你的背包 2021-01-03 17:55

I\'d like to expose a property on a view model that contains a list of objects (from database).

I need this collection to be read-only. That is, I want to prevent A

相关标签:
5条回答
  • 2021-01-03 18:15

    You could change the type of your property to be an IEnumerable:

    public IEnumerable<foo> CollectionOfFoo { 
         get { 
             return _CollectionOfFoo;
         }
    }
    

    I don't believe there is a standard interface that exposes an indexer. If you need it you could write an interface and extend ObservableCollection to implement it:

    public interface IIndexerCollection<T> : IEnumerable<T>
    {
        T this[int i]
        {
            get;
        }
    }
    
    public class IndexCollection<T> : ObservableCollection<T>, IIndexerCollection<T>
    {
    }
    
    0 讨论(0)
  • 2021-01-03 18:17

    Use ReadOnlyObservableCollection< T >

    public ReadOnlyObservableCollection<T> ReadOnlyFoo
    {
        get { return new ReadOnlyObservableCollection<T> (_CollectionOfFoo); }
    }
    

    As has been pointed out, please use Eric J's answer as this one mistakenly is returning a new instance every time.

    0 讨论(0)
  • 2021-01-03 18:19

    You could also override the list class that you're using and put an immutable flag in one of the constructors such that it will not add/remove if it was constructed with the immutable flag set to true.

    0 讨论(0)
  • 2021-01-03 18:22

    The [previously] accepted answer will actually return a different ReadOnlyObservableCollection every time ReadOnlyFoo is accessed. This is wasteful and can lead to subtle bugs.

    A preferable solution is:

    public class Source
    {
        Source()
        {
            m_collection = new ObservableCollection<int>();
            m_collectionReadOnly = new ReadOnlyObservableCollection<int>(m_collection);
        }
     
        public ReadOnlyObservableCollection<int> Items
        {
            get { return m_collectionReadOnly; }
        }
     
        readonly ObservableCollection<int> m_collection;
        readonly ReadOnlyObservableCollection<int> m_collectionReadOnly;
    }
    

    See ReadOnlyObservableCollection anti-pattern for a full discussion.

    0 讨论(0)
  • 2021-01-03 18:25

    I don't like using ReadOnlyObservableCollection<T> as it seems like a mistake / broken class; I prefer a contract based approach instead.

    Here is what I use that allows for covarience:

    public interface INotifyCollection<T> 
           : ICollection<T>, 
             INotifyCollectionChanged
    {}
    
    public interface IReadOnlyNotifyCollection<out T> 
           : IReadOnlyCollection<T>, 
             INotifyCollectionChanged
    {}
    
    public class NotifyCollection<T> 
           : ObservableCollection<T>, 
             INotifyCollection<T>, 
             IReadOnlyNotifyCollection<T>
    {}
    
    public class Program
    {
        private static void Main(string[] args)
        {
            var full = new NotifyCollection<string>();
            var readOnlyAccess = (IReadOnlyCollection<string>) full;
            var readOnlyNotifyOfChange = (IReadOnlyNotifyCollection<string>) full;
    
    
            //Covarience
            var readOnlyListWithChanges = 
                new List<IReadOnlyNotifyCollection<object>>()
                    {
                        new NotifyCollection<object>(),
                        new NotifyCollection<string>(),
                    };
        }
    }
    
    0 讨论(0)
提交回复
热议问题