完全执行此 MVVM,您的列表框项目将是您自己的某个类的实例的ObservableCollection,它代表您放入列表框中的任何内容(用户、二手车等)。该集合是您的视图模型上的一个属性。
在ListBox 结束时,您必须用间隔项表示空槽——null 应该可以。然后,您将在视图中使用 ListBox 的ItemTemplate 和ItemContainerStyle 来正确显示“空”项并防止它们被用户选中。您可能必须处理SelectionChanged 事件才能实现;如果你想以一种通用的方式重用这些东西,你可以通过你的样式将应用的附加属性来处理SelectionChanged。
选项 1,不是最纯粹的 MVVM,但比 Doing It Right 少了很多工作,非常简单:当您填充 ObservableCollection 时,对项目进行排序并为间隔项目插入空值。完毕。
<ListBox
ItemsSource="{Binding WeirdGappyCollectionWithNulls}"
ItemTemplate="{StaticResource GappyItemTemplate}"
ItemContainerStyle="{StaticResource GappyItemContainerStyle}"
/>
...其中GappyItemTemplate 和GappyItemContainerStyle 在上面的ResourceDictionary 中定义。
选项 2,如果您想使用 Full MVVMtard 并为年龄构建:
对于排序,我通常使用已排序的CollectionViewSource。然后你将它绑定到 ItemsSource
<ListBox
ItemTemplate="{StaticResource GappyItemTemplate}"
ItemContainerStyle="{StaticResource GappyItemContainerStyle}"
>
<ListBox.ItemsSource>
<local:GappyCollectionViewSource
Source="{Binding GappyCollection}"
...etc. etc.
/>
</ListBox.ItemsSource>
</ListBox>
我不希望视图模型有任何关于 ListBox 的线索,甚至是关于空项目的线索。
我会给视图模型一个“非空”项目的间隙集合,并编写一个CollectionViewSource 子类,该子类将按您喜欢的任何属性进行排序,并将该集合投影到另一个包含空“间隔”的只读集合项目,它在其View 属性中公开。
一种反过滤器。它可以使用SortDescriptions 来定义间隙是什么,至少在您按整数排序的情况下。或者,您可以通过给它一个 keyselector lambda 或类似于现有 Filter event 的事件来半快速和肮脏地完成该部分。
CollectionViewSource.View 不是虚拟属性,但它是DependencyProperty。应该有某种方法可以在那里滑入铃声。如果这给您带来任何麻烦,请改用CollectionView 重新开始。