模型 List<T> 和 ViewModel ObservableCollection<T> 重复数据?

Posted

技术标签:

【中文标题】模型 List<T> 和 ViewModel ObservableCollection<T> 重复数据?【英文标题】:Model List<T> and ViewModel ObservableCollection<T> Duplicate Data? 【发布时间】:2014-04-07 18:40:10 【问题描述】:

在需要在 UI 上显示的业务层中使用 List&lt;T&gt; 的最佳做法是什么?我目前在视图模型中使用带有ObservableCollection&lt;T&gt; 的数据绑定,它复制了List&lt;T&gt; 的数据。一个明显的问题是当List&lt;T&gt; 在业务层被修改时,ObservableCollection&lt;T&gt; 需要重新创建,所以List&lt;T&gt; 的更改会反映在 UI 中。这不是最好的方法。

我也不接受在业务层使用ObservableCollection&lt;T&gt; 作为答案。

谢谢!

【问题讨论】:

谁、何时以及如何在模型中修改您的List&lt;T&gt; 我正在寻找可以通过编程方式和/或通过 UI 修改列表而不复制数据的一般问题的解决方案。 “以编程方式”从哪里来?从模型本身?从虚拟机?请发布更多详细信息。 假设可以从视图模型或模型中修改列表。 【参考方案1】:

    如果你坚持让List&lt;T&gt; 和单独的事件通知列表修改,那么复制是唯一明智的方法。

      1234563 987654326@模式。

    如果您有精细的ItemChangedItemAdded 等事件,那么您实际上是在复制ObservableCollection&lt;T&gt; 功能。在这种情况下,您可以将您的应用程序包装在实现INotifyCollectionChanged 接口的代理集合中,但它会理解您的架构并将事件转换为适当的NotifyCollectionChangedAction

在业务层使用ObservableCollection&lt;T&gt; 一点也不坏。它是一个专门的集合,提供通用接口来通知项目更改,而不是专门为 WinForms 或 WPF 或其他什么设计的类。

【讨论】:

谢谢,我想我有一个先入为主的观念,即除非直接处理 UI,否则使用 ObservableCollection 是不好的。使用 ObservableCollection 时是否存在明显的可扩展性缺陷? @Rydel 查看问题ObservableCollection in the service layer of the WPF MVVM application,它有高质量的答案。【参考方案2】:

您可以实现 INotifyCollectionChanged 接口,但如果您想以一种可以保留您的实现的方式使用它,那么在实现您自己的类同时持有 IEnumerable 的实现的情况下,集合会做很多工作例如下面的内容,这是我用来保存所有将被更新的集合的基类,在这个实现中,变量_o​​rdering 中还有一个排序考虑:

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


当你有了这个实现后,你可以随意使用你的应用程序所需的所有集合,为自己制作一些 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);
    

当您在类中设置 _onCategoryRoot 时,您将显示的集合将通过 RaiseCollectionChanged() 方法进行更新,因此您需要在视图模型中添加Categories 类的属性并在 XAML 中设置绑定。

【讨论】:

以上是关于模型 List<T> 和 ViewModel ObservableCollection<T> 重复数据?的主要内容,如果未能解决你的问题,请参考以下文章

MVC - 将动态添加的控件绑定到模型中的 List<T>

返回和转换 ResponseEntity<List<T>>

Dagger/MissingBinding java.util.Map<java.lang.Class<? extends ViewModel>,Provider<ViewMo

Moshi 适配器跳过 List<T> 中的坏对象

如何从 C# 中的通用 List<T> 中获取元素? [复制]

在 MVC 5 中,如何将表对象数据作为列表传递给控制器​​视图模型?