C# 模型列表<;T>;和ViewModel ObservableCollection<;T>;重复数据?

C# 模型列表<;T>;和ViewModel ObservableCollection<;T>;重复数据?,c#,wpf,list,mvvm,observablecollection,C#,Wpf,List,Mvvm,Observablecollection,在业务层中有一个需要显示在UI上的列表的最佳实践是什么?我目前在viewmodel中使用带有ObservableCollection的数据绑定来复制列表的数据。这方面的一个明显问题是,当在业务层修改列表时,需要重新创建可观察集合,以便将列表的更改反映在UI中。这不是最好的办法 我也不会接受在业务层中使用observateCollection作为答案 谢谢 如果您坚持让列表和单独的事件通知列表修改,那么复制是唯一明智的方法 如果您有ListChanged事件,但没有关于实际更改内容的详细信息,您可

在业务层中有一个需要显示在UI上的
列表
的最佳实践是什么?我目前在viewmodel中使用带有
ObservableCollection
的数据绑定来复制
列表的数据。这方面的一个明显问题是,当在业务层修改
列表时,需要重新创建
可观察集合
,以便将
列表
的更改反映在UI中。这不是最好的办法

我也不会接受在业务层中使用
observateCollection
作为答案

谢谢

  • 如果您坚持让
    列表
    和单独的事件通知列表修改,那么复制是唯一明智的方法

  • 如果您有
    ListChanged
    事件,但没有关于实际更改内容的详细信息,您可以避免重复,只需将列表包装在代理集合中,实现
    INotifyCollectionChanged
    接口,该接口将在
    NotifyCollectionChangedAction.Reset
    模式下触发相应的
    CollectionChanged
    事件

  • 如果您有粒度
    ItemChanged
    itemsadded
    等事件,那么您实际上是在复制
    observedcollection
    功能。在这种情况下,您可以将应用程序包装在代理集合中,实现
    INotifyCollectionChanged
    接口,但该接口可以理解您的体系结构并将事件转换为适当的
    NotifyCollectionChangedAction

  • 在业务层中使用
    ObservableCollection
    一点也不坏。它是一个专门的集合,提供公共接口来通知项的更改,而不是专门为WinForms或WPF等设计的类


  • 您可以实现INotifyCollectionChanged接口,但是如果您想以一种可以保持实现的方式使用它,那么在实现您自己的类的情况下,集合也可以保持IEnumerable的实现,这将为您做大量的工作,例如:,这是我用来保存将要更新的所有集合的基类,在这个实现中,变量_ordering中还考虑了排序问题:

    public abstract class BaseINotifyCollectionChanged<T, K> : INotifyCollectionChanged, IEnumerable<T>
    {
        Func<T, K> _ordering;
        bool _ascending;
    
        public BaseINotifyCollectionChanged()
        {
        }
    
        public BaseINotifyCollectionChanged(Func<T, K> ordering, bool ascending = true)
        {
            _ordering = ordering;
            _ascending = ascending;
            OnCollectionChanged();
        }
    
        protected abstract IList<T> GetCollection();
    
        public event NotifyCollectionChangedEventHandler CollectionChanged;
        protected void OnCollectionChanged()
        {
            if (CollectionChanged != null)
                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }
        public void RaiseCollectionChanged()
        {
            OnCollectionChanged();
        }
    
        public IEnumerator<T> GetEnumerator()
        {
            return _ordering == null ? GetCollection().GetEnumerator() : _ascending ? GetCollection().OrderBy<T, K>(_ordering).GetEnumerator() :
                                                                                      GetCollection().OrderByDescending<T, K>(_ordering).GetEnumerator();
        }
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return _ordering == null ? GetCollection().GetEnumerator() : _ascending ? GetCollection().OrderBy<T, K>(_ordering).GetEnumerator() :
                                                                                      GetCollection().OrderByDescending<T, K>(_ordering).GetEnumerator();
        }
    }
    }
    
    公共抽象类BaseINotifyCollectionChanged:INotifyCollectionChanged,IEnumerable
    {
    Func_排序;
    bool_上升;
    public BaseINotifyCollectionChanged()
    {
    }
    public BaseINotifyCollectionChanged(函数排序,布尔升序=true)
    {
    _排序=排序;
    _上升=上升;
    OnCollectionChanged();
    }
    受保护的抽象IList GetCollection();
    公共事件通知CollectionChangedEventHandler CollectionChanged;
    CollectionChanged()上受保护的void
    {
    如果(CollectionChanged!=null)
    CollectionChanged(这是新的NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }
    public void RaiseCollectionChanged()
    {
    OnCollectionChanged();
    }
    公共IEnumerator GetEnumerator()
    {
    return _ordering==null?GetCollection().GetEnumerator():_升序?GetCollection().OrderBy(_ordering).GetEnumerator():
    GetCollection().OrderByDescending(_ordering).GetEnumerator();
    }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
    return _ordering==null?GetCollection().GetEnumerator():_升序?GetCollection().OrderBy(_ordering).GetEnumerator():
    GetCollection().OrderByDescending(_ordering).GetEnumerator();
    }
    }
    }
    
    当你有了这个实现后,你可以随心所欲地使用它,并在你的应用程序上完成你需要的所有集合,为自己制作一些dry,下面是你可以使用这个抽象类的一个例子:

    public class Categories : BaseINotifyCollectionChanged<Category, string>
    {
        long _onCategoryRoot;
        public void SetOnCategoryRoot(long categoryId)
        {
            _onCategoryRoot = categoryId;
            RaiseCollectionChanged();
        }
    
        protected override IList<Category> GetCollection()
        {
            Category category = new Category();
            return _onRoot ? category.GetRootCategories() : category.GetSubCategoriesOnRoot(_onCategoryRoot);
        }
    }
    
    公共类类别:BaseINotifyCollectionChanged
    {
    长_onCategoryRoot;
    公共无效SetOnCategoryRoot(长类别ID)
    {
    _onCategoryRoot=类别ID;
    RaiseCollectionChanged();
    }
    受保护的覆盖IList GetCollection()
    {
    类别=新类别();
    return _onRoot?category.GetRootCategories():category.GetSubCategoriesOnRoot(_onCategoryRoot);
    }
    }
    

    在类中设置\u onCategoryRoot时,将通过RaiseCollectionChanged()方法更新要显示的集合,因此,您需要在viewmodel中添加一个类为Categories的属性,并在XAML中设置绑定。

    谁、何时以及如何在模型中修改
    列表
    ?我正在寻找一种解决方案,以解决一般问题,即可以通过编程或通过UI修改列表,而无需复制数据。“在程序上“从哪里来?从模型本身?来自虚拟机?请发布更多详细信息。假设可以从viewmodel或model修改列表。谢谢,我想我有一个先入为主的想法,即除非直接处理UI,否则使用ObservableCollection是不好的。当使用ObservableCollection时,在扩展性方面是否存在明显的缺陷?@Rydel看到这个问题,它有高质量的答案。