wpf mvvm:为什么在绑定到树视图时在视图模型中复制模型集合?怎么避免呢?

时间:2016-11-11 06:11:16

标签: wpf mvvm collections treeview

我的模型中有一个由级别和实体组成的2级层次结构,托管在根对象中,我希望在TreeView中显示它们。

Root object L Constellations L Entities

我的RootObjectViewModel暴露了我的根对象。在那,我完全同意在MVVM best practices中的Bryan Lagunas,模型对象应该由视图模型公开而不是外观。顺便说一句优秀的视频,真的值得花时间。

我到处读到TreeView.ItemsSource应该映射到一组视图模型,也就是说,对于我的Constellation集合,我的RootObjectViewModel应该提供ConstellationViewModel的集合。 我担心的是,如果我的星座集合和其中的实体是实时的,也就是说,如果某些项目被添加,更改(它们的顺序)或被删除,我必须在我的ViewModels集合中手动反映这些变化。

我会发现将ItemsSource映射到Constellation本身的集合会更优雅,这样模型中的任何更改都会反映出来而不会重复,然后有一些转换器来映射{ {1}}基于星座模型TreeViewItems.DataContext

如果这还不够清楚,我可以用一些示例代码来澄清这一点。

是否有人面临同样的问题和/或尝试实施此问题?

提前感谢您的帮助。

塞德里克

2 个答案:

答案 0 :(得分:0)

这取决于。如果您的模型具有视图所需的属性,并且视图可以在用户点击时直接更改它们,则可以公开模型。

但是,如果您的模型是,例如,只读并需要调用服务来应用更改,则必须将其包装在视图模型中,以便为视图提供可写属性。

答案 1 :(得分:0)

搞定了!

不可能开箱即用,这就是原因:

可以将模型集合用作项目源,并使用转换器来获取TreeViewItem内部组件的相应视图模型。但是没有任何方法可以干扰创建TreeViewItem以将转换器应用于其DataContext。这意味着TreeViewItem的属性无法绑定到ViewModel。

换句话说:

  • 如果您希望坚持TreeView的标准行为,而不必处理TreeViewItems属性,如果您的集合未更改或可以实现{{1}如果你的模型没有改变或者可以实现ICollectionChanged,那么可以使用模型的集合。
  • 如果这些条件中的任何一个被破坏,那么你将不得不构建ViewModel的集合并将它们与模型的集合同步。

现在,我实现了一个名为IPropertyChanged的集合类型,它使用原始集合作为输入,并使用此输入同步其自己的内容。这只是一个基础课程,有许多改进方法,但它有效。您所要做的就是将此集合用作VM属性,设置原始集合和转换器,并将ItemsSource绑定到此集合。

这是完整的代码:

ConvertingCollection<Tin, Tout>

我在Github上创建了一个名为MVVMTreeViewPOC的项目给POC这个想法。它工作正常,它是展示限制的好工具。

塞德里克。