C# IObservableCollection<;视图模型<;T>&燃气轮机;包装可观察收集<;T>;

C# IObservableCollection<;视图模型<;T>&燃气轮机;包装可观察收集<;T>;,c#,wpf,mvvm,design-patterns,C#,Wpf,Mvvm,Design Patterns,在C#/WPF中,提供一个实现IObservableCollection并从模型中包装observedcollection的类的最佳方式是什么 模型可以向基础集合添加/删除T元素,或者视图可以从视图模型层添加/删除ViewModel元素 从MVVM模式的角度来看,这有什么可疑之处吗?是否有包含此类或类似类的库?我在下面编写了一个类,可用于单线程目的。我只实现了添加和删除,所以您必须实现您可能使用的任何其他操作: 用法: var viewModelWrapper = new ObservableC

在C#/WPF中,提供一个实现
IObservableCollection
并从模型中包装
observedcollection
的类的最佳方式是什么

模型可以向基础集合添加/删除T元素,或者视图可以从视图模型层添加/删除ViewModel元素


从MVVM模式的角度来看,这有什么可疑之处吗?是否有包含此类或类似类的库?

我在下面编写了一个类,可用于单线程目的。我只实现了添加和删除,所以您必须实现您可能使用的任何其他操作:

用法:

var viewModelWrapper = new ObservableCollectionViewModel<ItemViewModel, Model>(Model.List, item => new ItemViewModel(item));
var viewModelWrapper=newobserveCollectionViewModel(Model.List,item=>newitemViewModel(item));
泛型类-可观察集合视图模型包装器:

public class ObservableCollectionViewModel<TItemViewModel, TModel> :
    ObservableCollection<TItemViewModel>, IDisposable
    where TItemViewModel : BaseViewModel<TModel>
    where TModel : new()
{
    private readonly ObservableCollection<TModel> models;
    private readonly Func<TModel, TItemViewModel> viewModelConstructor;

    public ObservableCollectionViewModel(ObservableCollection<TModel> models,
        Func<TModel, TItemViewModel> viewModelConstructor)
    {
        this.models = models;
        this.viewModelConstructor = viewModelConstructor;
        CreateViewModelCollection();
        models.CollectionChanged += models_CollectionChanged;
        CollectionChanged += viewModels_CollectionChanged;
    }

    private void viewModels_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        models.CollectionChanged -= models_CollectionChanged;
        try
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    {
                        foreach (var newItem in e.NewItems)
                        {
                            models.Add(((TItemViewModel)newItem).Model);
                        }
                        break;
                    }
                case NotifyCollectionChangedAction.Remove:
                    {
                        foreach (var oldItem in e.OldItems)
                        {
                            models.Remove(((TItemViewModel)oldItem).Model);
                        }
                        break;
                    }
                // TODO: Add missing actions
                default: throw new NotImplementedException();
            }
        }
        finally
        {
            models.CollectionChanged += models_CollectionChanged;
        }
    }

    private void models_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        CollectionChanged -= viewModels_CollectionChanged;
        try
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    {
                        foreach (var newItem in e.NewItems)
                        {
                            Add(viewModelConstructor((TModel)newItem));
                        }
                        break;
                    }
                case NotifyCollectionChangedAction.Remove:
                    {
                        var viewModels = this.Where(viewModel => e.OldItems.Contains(viewModel.Model)).ToList();
                        foreach (var viewModel in viewModels)
                        {
                            Remove(viewModel);
                        }
                        break;
                    }
                // TODO: Add missing actions
                default: throw new NotImplementedException();
            }
        }
        finally
        {
            CollectionChanged += viewModels_CollectionChanged;
        }
    }

    /// <summary>
    /// Only called once, by constructor
    /// </summary>
    private void CreateViewModelCollection()
    {
        foreach (var model in models)
        {
            Add(viewModelConstructor(model));
        }
    }

    public void Dispose()
    {
        models.CollectionChanged -= models_CollectionChanged;
    }
}
公共类ObservableCollectionViewModel:
可观察的收集,可识别的
其中TItemViewModel:BaseViewModel
其中TModel:new()
{
私有只读可观察收集模型;
私有只读Func viewModelConstructor;
公共ObservableCollectionViewModel(ObservableCollectionModels,
Func视图模型(构造函数)
{
这个。模型=模型;
this.viewModelConstructor=viewModelConstructor;
CreateViewModelCollection();
models.CollectionChanged+=models\u CollectionChanged;
CollectionChanged+=视图模型\u CollectionChanged;
}
private void viewModels\u CollectionChanged(对象发送方,NotifyCollectionChangedEventArgs e)
{
models.CollectionChanged-=models\u CollectionChanged;
尝试
{
开关(电动)
{
案例NotifyCollectionChangedAction。添加:
{
foreach(e.NewItems中的var newItem)
{
models.Add(((TItemViewModel)newItem).Model);
}
打破
}
案例NotifyCollectionChangedAction。删除:
{
foreach(e.OldItems中的var oldItem)
{
移除(((TItemViewModel)oldItem).Model);
}
打破
}
//TODO:添加缺少的操作
默认值:抛出新的NotImplementedException();
}
}
最后
{
models.CollectionChanged+=models\u CollectionChanged;
}
}
私有void模型\u CollectionChanged(对象发送方,NotifyCollectionChangedEventArgs e)
{
CollectionChanged-=viewModels\u CollectionChanged;
尝试
{
开关(电动)
{
案例NotifyCollectionChangedAction。添加:
{
foreach(e.NewItems中的var newItem)
{
添加(viewModelConstructor((TModel)newItem));
}
打破
}
案例NotifyCollectionChangedAction。删除:
{
var viewModels=this.Where(viewModel=>e.OldItems.Contains(viewModel.Model)).ToList();
foreach(视图模型中的var viewModel)
{
移除(视图模型);
}
打破
}
//TODO:添加缺少的操作
默认值:抛出新的NotImplementedException();
}
}
最后
{
CollectionChanged+=视图模型\u CollectionChanged;
}
}
/// 
///构造函数只调用一次
/// 
私有void CreateViewModelCollection()
{
foreach(模型中的var模型)
{
添加(viewModelConstructor(模型));
}
}
公共空间处置()
{
models.CollectionChanged-=models\u CollectionChanged;
}
}

仅包含类型为
ObservableCollection
甚至
ObservableCollection
的属性的类有什么问题?我一直不明白为什么人们总是想写一些继承自
ObservableCollection
的东西。。。它就像一个
列表
,但带有更改通知。您不应该覆盖
List
来创建一个数据类,也不应该覆盖
observedcollection
(除非它是为了扩展列表/集合的功能)@Rachel我有一个列表视图,其中每个项目都是
ItemModel
,我需要将它们包装在
ItemViewModel
中。在MVVM模式中,模型不应该直接暴露于视图中。“MVVM纯粹主义”方法是从不将模型暴露于视图中,但通常这样做更为实际,因此两种方法都是有效的。即使您想坚持这种设计模式,我仍然不明白您为什么要覆盖
observateCollection
。取而代之的是,您的ViewModel应该包含一个类型为
ObservableCollection
的属性,而
SomeViewModel
应该公开
SomeModel
@dbkk的属性:只要您在将数据发送到服务器之前验证数据,我看不出视图查看某些模型部件有什么问题。@jberger当然,有多种方法可以剥猫的皮,但我想知道从MVVM的角度来看,什么方法是可取的。