WPF绑定到Model对象列表的ViewModel列表

在模型中,我有:

public ObservableCollection Items { get; private set; } 

在ViewModel中,我有一个相应的ItemViewModel列表。 我希望这个列表与模型列表双向绑定:

 public ObservableCollection ItemViewModels ... 

在XAML中,我将绑定(在本例中为TreeView)到ItemViewModels属性。

我的问题是,上面显示的ViewModel中的“…”是什么? 我希望一行或两行代码绑定这两个ObservableCollections(提供ViewModel的类型来为每个模型对象构造)。 但是,我担心的是需要处理Items.CollectionChanged事件的一堆代码,并根据需要通过构造ViewModels手动更新ItemViewModels列表,并根据对ItemViewModels的更改来更新Items集合。

谢谢!

埃里克

您可以使用以下类:

 public class BoundObservableCollection : ObservableCollection { private ObservableCollection _source; private Func _converter; private Func _isSameSource; public BoundObservableCollection( ObservableCollection source, Func converter, Func isSameSource) : base() { _source = source; _converter = converter; _isSameSource = isSameSource; // Copy items AddItems(_source); // Subscribe to the source's CollectionChanged event _source.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_source_CollectionChanged); } private void AddItems(IEnumerable items) { foreach (var sourceItem in items) { Add(_converter(sourceItem)); } } void _source_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { switch (e.Action) { case NotifyCollectionChangedAction.Add: AddItems(e.NewItems.Cast()); break; case NotifyCollectionChangedAction.Move: // Not sure what to do here... break; case NotifyCollectionChangedAction.Remove: foreach (var sourceItem in e.OldItems.Cast()) { var toRemove = this.First(item => _isSameSource(item, sourceItem)); this.Remove(toRemove); } break; case NotifyCollectionChangedAction.Replace: for (int i = e.NewStartingIndex; i < e.NewItems.Count; i++) { this[i] = _converter((TSource)e.NewItems[i]); } break; case NotifyCollectionChangedAction.Reset: this.Clear(); this.AddItems(_source); break; default: break; } } } 

使用方法如下:

 var models = new ObservableCollection(); var viewModels = new BoundObservableCollection( models, m => new ViewModel(m), // creates a ViewModel from a Model (vm, m) => vm.Model.Equals(m)); // checks if the ViewModel corresponds to the specified model 

ObservableCollection将改变时, BoundObservableCollection将被更新,但不是相反(你必须覆盖一些方法来做到这一点)

是的,你的恐惧是真的,你必须包装所有ObservableCollectionfunction。

我的回答问题是,为什么你想要看看模型包装器已经看起来好看的模型? 如果您的数据模型基于某些不可绑定的业务逻辑,则View模型非常有用。 通常,此业务/数据层具有一种或两种方式来检索数据并通知外部观察者其更改,这些更改可由视图模型轻松处理并转换为对ObservableCollection更改。 实际上在.NET 3.5中, ObservableCollectionWindowsBase.dll的一部分,因此通常它首先不会在数据模型中使用。

我的建议是填充/修改ObservableCollection的逻辑应该从您的数据模型移动到视图模型中,或者您应该直接绑定到您当前调用数据模型的层,并且只需调用它就是什么。 视图模型。

你可以显然写一个帮助类,它将使用一些转换器lambdas(从ItemItemViewModel和向后)同步两个集合,并在这样的地方使用它(确保你正确处理项目唯一性),但是恕我直言这种方法产生多余包装类的数量,每个层都会减少function并增加复杂性。 这与MVVM目标完全相反。