wpf 如何创建只读的ObservableCollection属性?

n53p2ov0  于 2023-03-31  发布在  其他
关注(0)|答案(5)|浏览(203)

我想公开一个视图模型的属性,其中包含一个对象列表(来自数据库)。
我需要这个集合是只读的。也就是说,我想阻止添加/删除等操作,但允许foreach和索引器工作。我的意图是声明一个私有字段,保存可编辑的集合,并使用只读的Public Property引用它。如下所示

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

然而,这种语法只是阻止了对集合的引用的改变,并没有阻止添加/删除等操作。
实现这一目标的正确方法是什么?

643ylb08

643ylb081#

解决方案是:

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

参见ReadOnlyObservableCollection anti-pattern以获得完整的讨论。
请注意,每次访问ReadOnlyFoo时,[previously] accepted answer实际上会返回一个不同的ReadOnlyObservableCollection。这是浪费的,可能会导致细微的bug。

guz6ccqo

guz6ccqo2#

我不喜欢使用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>(),
                };
    }
}
9cbw7uwe

9cbw7uwe3#

您可以将属性的类型更改为IEnumerable:

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

我不相信有一个标准的接口来公开索引器。如果你需要它,你可以写一个接口并扩展ObservableCollection来实现它:

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

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

ozxc1zmp4#

你也可以覆盖你正在使用的list类,并在其中一个构造函数中放置一个immutable标志,这样如果它是在immutable标志设置为true的情况下构造的,它就不会添加/删除。

2uluyalo

2uluyalo5#

使用ReadOnlyObservableCollection< T >

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

正如已经指出的那样,请使用Eric J的答案,因为这个答案每次都错误地返回一个新示例。

相关问题