我正在学习 .NET 和 WPF,同时构建一个小型待办事项列表(如应用程序)。
我试图了解 ICollectionView 接口和 CollectionViewSource 如何与 MVVM 模式一起使用,而不破坏它。据我所知,它们是 WPF 类型,并且在 ViewModel 中使用它们将 View 和 ViewModel 强耦合在一起。
我的应用程序主要是一个数据网格,其中有一些包含命令的按钮。 ViewModel 内的命令调用一个分配结果的方法,并使用
CollectionViewSource.GetDefaultView(Object).MoveCurrentToNext()
移动到下一行
视图模型
public RelayCommand TestPassedCommand => new RelayCommand(execute => TestPassed(), canExecute => SelectedItem != null);
private void TestPassed()
{
if(_selectedItem != null)
{
_selectedItem.Result = ResultEnum.passed;
}
ICollectionView view = CollectionViewSource.GetDefaultView(HardwareTests);
view.MoveCurrentToNext();
}
我尝试过的
我删除了调用方法
MoveCurrentToNext()
的部分代码,并在代码隐藏中添加了一个EventHandler(这也破坏了MVVM)。单击按钮时,在上面的命令之前执行事件处理程序,尽管它仍然有效,但我不喜欢这种方法。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void MarkTestPassed(object sender, RoutedEventArgs e)
{
if(DataGrid.SelectedItem != null)
{
ICollectionView view = CollectionViewSource.GetDefaultView(DataGrid.ItemsSource);
view.MoveCurrentToNext();
}
}
}
无论您是否想在视图模型类中使用
CollectionViewSource
,这完全取决于个人设计选择。 MVVM 不关心这种情况。
“我读过它们是 WPF 类型,并且在 ViewModel 中使用它们与视图强耦合”
仔细想想,这没有道理。您似乎认为所有 WPF 类型都与视图相关。事实并非如此。视图模型类中使用的最著名的类型是
INotifyPropertyChanged
。如果视图模型类型引用视图类型,则视图模型与视图之间只会存在强耦合。 WPF 类型既不是视图类型也不是视图模型类型。它们首先是框架类型。使用框架类型只能创建与框架的强耦合,这通常是您想要的,因为这就是框架的工作方式(IoC)。
在 MVVM 中,一切都与责任有关。当控件呈现并与用户交互时,视图模型不允许实例化控件,这是应用程序视图的责任。这是关键标准,而不是事实,例如StackPanel
是 WPF 类型。
“我删除了调用 MoveCurrentToNext() 方法的部分代码,并在代码隐藏中添加了一个 EventHandler(这也破坏了 MVVM)。”
你从哪里学来的? Microsoft 从未将代码隐藏与 MVVM 设计模式相关。根据定义,设计模式必须与语言和编译器无关。代码隐藏是一种通过部分类概念实现的语言功能。
MVVM 不关心您是否使用 XAML、C#、VB.NET 还是 C。它只关心应用程序结构、构成该结构的组件(视图、视图模型、模型)之间的依赖关系以及定义是否类型与视图、视图模型或模型应用程序组件相关联。 MVVM 不关心你使用的是命令还是事件。但它关心视图模型中的命令是否执行视图相关的职责,例如显示一个对话框。
如果您的事件处理程序没有因为执行错误的职责而破坏 MVVM,那么它也不会破坏 MVVM。事件处理程序本身不是问题。事件处理程序所做的就是相关的。
“我试图了解 ICollectionView 接口和 CollectionViewSource 如何与 MVVM 模式一起使用,而不破坏它。”
CollectionViewSource
是一个辅助类,是获取视图模型类集合的默认集合视图的唯一方法(ItemsControl.Items
当然不是一个选项,因为这会破坏 MVVM)。CollectionViewSource
的依赖,那么应该清楚这是一个与 MVVM 无关的设计决策。
通常,您使用
ICollectionView
对集合进行排序、过滤和分组。这些集合操作是否属于视图或视图模型取决于上下文。关键是视图或尤其是控件应该与数据无关。 DataGrid
可以在不知道数据类型的情况下执行基本排序。按属性排序需要这些知识,因此通常在存在这些知识的视图模型中实现。并且您始终可以在视图组件中获取默认的 ICollectionView
并将其传递给视图模型组件。使用 CollectionViewSource
还允许在 XAML 中定义排序描述。
无论您是否想在视图模型类中使用
CollectionViewSource
,这完全取决于个人设计选择。 MVVM 不关心这种情况。