如何创建只读的ObservableCollection属性?

thr*_*rag 36 .net c# wpf observablecollection

我想在包含对象列表(来自数据库)的视图模型上公开属性.

我需要这个集合是只读的.也就是说,我想阻止添加/删除等.但是允许foreach和indexers工作.我的目的是声明一个包含可编辑集合的私有字段,并使用只读公共属性引用它.如下

public ObservableCollection<foo> CollectionOfFoo { 
     get { 
         return _CollectionOfFoo;
     }
}
Run Code Online (Sandbox Code Playgroud)

但是,该语法只会阻止更改对集合的引用.它不会阻止添加/删除等

完成此任务的正确方法是什么?

Eri*_* J. 61

每次访问ReadOnlyFoo时,[先前]接受的答案实际上将返回不同的 ReadOnlyObservableCollection.这很浪费,可能导致细微的错误.

一个好的解决方案是:

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;
}
Run Code Online (Sandbox Code Playgroud)

有关完整讨论,请参阅ReadOnlyObservableCollection反模式.

  • 您可以通过使`Items`成为具有私有setter的auto属性来删除对`m_collectionReadOnly`的需要,并且只需在构造函数中设置一次.然后,您可以拥有更清洁的代码,并且您不必担心每次访问时都要创建新实例. (2认同)
  • 使用C#6,您现在也可以使用隐式只读设置器`... {get; },只能从构造函数中赋值.然后你最好的两个. (2认同)

Mei*_*hes 9

我不喜欢使用,ReadOnlyObservableCollection<T>因为它似乎是一个错误/破碎的课程; 我更喜欢基于合同的方法.

以下是我使用的允许共变的内容:

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>(),
                };
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 非常好,优雅.我比使用`ReadOnlyObservableCollection <T>`类更喜欢这个.也就是说,值得注意的是,使用`ReadOnlyObservableCollection <T>`的一个好处是类型本身只是_不支持修改.使用这个解决方案,你不会受到粗心编码器的保护,他们只是将实例强制转换为可写类型(即`NotifyCollection <T>`,`INotifyCollection <T>`,`IList <T>`等).相信我,在任何足够大的团队中,如果可以的话,至少有一个人会这样做. (3认同)