que c# .net wpf observablecollection

c# - que - observablecollection methods



¿Cómo puedo hacer una propiedad ObservableCollection de solo lectura? (5)

La respuesta [previamente] aceptada devolverá una ReadOnlyObservableCollection diferente cada vez que se acceda a ReadOnlyFoo. Esto es un desperdicio y puede conducir a errores sutiles.

Una solución preferible es:

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; }

Ver el antipatrón de ReadOnlyObservableCollection para una discusión completa.

Me gustaría exponer una propiedad en un modelo de vista que contiene una lista de objetos (desde la base de datos).

Necesito que esta colección sea de solo lectura. Es decir, quiero evitar Agregar / Eliminar, etc. Pero permita que los foreach y los indexadores funcionen. Mi intención es declarar un campo privado que contiene la colección editable y hacer referencia a ella con una propiedad pública de solo lectura. Como sigue

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

Sin embargo, esa sintaxis simplemente impide cambiar la referencia a la colección. No impide agregar / eliminar, etc.

¿Cuál es la forma correcta de lograr esto?


No me gusta usar ReadOnlyObservableCollection<T> ya que parece un error / clase rota; Prefiero un enfoque basado en contrato en su lugar.

Esto es lo que uso que permite la covariación:

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>(), }; } }


Puede cambiar el tipo de su propiedad para que sea un IEnumerable:

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

No creo que exista una interfaz estándar que exponga a un indexador. Si lo necesita, puede escribir una interfaz y extender ObservableCollection para implementarlo:

public interface IIndexerCollection<T> : IEnumerable<T> { T this[int i] { get; } } public class IndexCollection<T> : ObservableCollection<T>, IIndexerCollection<T> { }


También puede anular la clase de lista que está utilizando y colocar un indicador inmutable en uno de los constructores de modo que no se agregue / elimine si se construyó con el indicador inmutable establecido en verdadero.


Utilice ReadOnlyObservableCollection <T>

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

Como se ha señalado, utilice la respuesta de Eric J ya que esta devuelve una nueva instancia por error.