41 votes

Comment créer une propriété ObservableCollection en lecture seule?

J'aimerais exposer une propriété sur un modèle d'affichage qui contient une liste d'objets (à partir de la base de données).

J'ai besoin de cette collection à être en lecture seule. C'est, je veux éviter d'Ajouter/Supprimer, etc. Mais autoriser le foreach et les indexeurs de travail. Mon intention est de déclarer un champ privé détenant les formulaires de collecte et de référence avec un Public en lecture seule Propriété. Comme suit

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

Cependant, cette syntaxe empêche la modification de la référence à la collection. Cela ne les empêche pas d'ajouter/supprimer, etc.

Quelle est la bonne façon d'accomplir cette?

68voto

Eric J. Points 73338

La réponse acceptée [précédemment] renverra en fait une ReadOnlyObservableCollection différente chaque fois que ReadOnlyFoo est accédé. C'est du gaspillage et peut conduire à des bugs subtils.

Une solution préférable est:

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

Voir l' anti-modèle ReadOnlyObservableCollection pour une discussion complète.

11voto

Meirion Hughes Points 1855

Je n'aime pas utiliser ReadOnlyObservableCollection<T> car cela semble être une erreur / classe cassée; Je préfère plutôt une approche contractuelle.

Voici ce que j'utilise qui permet la 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>(),
                };
    }
}
 

0voto

Jake Pearson Points 9657

Vous pouvez changer le type de votre propriété pour qu'elle soit un IEnumerable:

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

Je ne crois pas qu'il existe une interface standard qui expose un indexeur. Si vous en avez besoin, vous pouvez écrire une interface et étendre ObservableCollection pour l'implémenter:

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

public class IndexCollection<T> : ObservableCollection<T>, IIndexerCollection<T>
{
}
 

-1voto

JERiv Points 194

Vous pouvez également remplacer la classe de liste que vous utilisez et placer un indicateur immuable dans l'un des constructeurs de manière à ce qu'il ne soit pas ajouté / supprimé s'il a été construit avec l'indicateur immuable défini sur true.

-1voto

scwagner Points 3063

Utilisez ReadOnlyObservableCollection <T>

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

Comme cela a été souligné, veuillez utiliser la réponse d'Eric J car celle-ci renvoie par erreur une nouvelle instance à chaque fois.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X