Wpf 具有撤消/重做功能的DataGrid和MVVM

Wpf 具有撤消/重做功能的DataGrid和MVVM,wpf,mvvm,datagrid,undo-redo,Wpf,Mvvm,Datagrid,Undo Redo,我正在玩一个非常简单的界面,带有按钮和快捷方式,用于添加、插入和删除datagrid底层绑定集合的行。 还需要实现撤销堆栈。 但是…我不知道如何处理这个控制的内部逻辑。 默认情况下,DataGrid可以自动删除或添加新行,并对用户输入Esc、F2等执行许多其他操作,从而隐式更改绑定的数据 由于要在VM端执行命令,撤销堆栈是其业务,甚至是M的业务,但DataGrid包含到DataGrid的内部预定义绑定。命令。我看不到“观察”数据变化的简单方法 我对理想的MVVM流的理解如下: 用户操作视图->命

我正在玩一个非常简单的界面,带有按钮和快捷方式,用于添加、插入和删除datagrid底层绑定集合的行。 还需要实现撤销堆栈。 但是…我不知道如何处理这个控制的内部逻辑。 默认情况下,DataGrid可以自动删除或添加新行,并对用户输入Esc、F2等执行许多其他操作,从而隐式更改绑定的数据

由于要在VM端执行命令,撤销堆栈是其业务,甚至是M的业务,但DataGrid包含到DataGrid的内部预定义绑定。命令。我看不到“观察”数据变化的简单方法

我对理想的MVVM流的理解如下: 用户操作视图->命令虚拟机->命令执行+撤消堆栈操作。VM-M ->UI分别更改为VM更改


我很困惑,需要一些关于实现的好建议。

因为您的DataGrid绑定到一个集合,所以您可以监视集合本身而不是DataGrid的更改。使用集合上的CollectionChanged事件监视添加或删除的项,并在集合的所有项上注册PropertyChanged事件以监视编辑


另一种想法是提供一个RevertChanges命令,而不是UndoChanges。它的实现要简单得多,因为您只需要存储原始集合,以便在需要时还原它。

由于您的DataGrid绑定到集合,因此您可以监视对集合本身而不是DataGrid的更改。使用集合上的CollectionChanged事件监视添加或删除的项,并在集合的所有项上注册PropertyChanged事件以监视编辑


另一种想法是提供一个RevertChanges命令,而不是UndoChanges。它的实现要简单得多,因为您只需要存储原始集合,这样您就可以在需要时恢复它。

通常我将撤销逻辑构建到模型本身中。在您开始考虑如何将它们绑定到UI之前,让它们完全按照您想要的方式工作。

通常我会将撤销逻辑构建到模型本身中。在您开始考虑如何将它们绑定到UI之前,让它们完全按照您想要的方式工作。

2种方法:

在ViewModel POCO模型上显示所有逻辑

您必须让ViewModel包含撤消/重做堆栈。如何实现它取决于您自己,但我建议只使用Tuple的Undo/Redo堆栈。存储属性名称和属性值。这比管理克隆更容易。它还可以让你通过查看UndoStack上是否有物品来检查穷人的肮脏程度

为您的模型提供一些接口,例如IUndoRedo富模型

您必须让ViewModels调用接口方法来撤消/重做,但想法是一样的。。。具有由元组组成的撤消/重做堆栈

如果您决定采用富模型方法,您可以查看现有的框架,例如为富模型设计的框架,尽管它可能比您真正需要的要多一些。只要把它扔出去,以防你想拥有真正富有的模特

旁注:您是ObservableCollection项资源应该是ViewModels,而不是Models。如果你用的是模型,就把它扔出去。也就是说,不要进行可观察收集,而是进行可观察收集。它使事情变得更简单,更容易和更可重用


另一个注意事项:尽量避免使用DataGrid。这让开发者们想把头发扯下来。我只想使用ListView推出您自己的网格:

2种方法:

在ViewModel POCO模型上显示所有逻辑

您必须让ViewModel包含撤消/重做堆栈。如何实现它取决于您自己,但我建议只使用Tuple的Undo/Redo堆栈。存储属性名称和属性值。这比管理克隆更容易。它还可以让你通过查看UndoStack上是否有物品来检查穷人的肮脏程度

为您的模型提供一些接口,例如IUndoRedo富模型

您必须让ViewModels调用接口方法来撤消/重做,但想法是一样的。。。具有由元组组成的撤消/重做堆栈

如果您决定采用富模型方法,您可以查看现有的框架,例如为富模型设计的框架,尽管它可能比您真正需要的要多一些。只要把它扔出去,以防你想拥有真正富有的模特

旁注:您是ObservableCollection项资源应该是ViewModels,而不是Models。如果你用的是模型,就把它扔出去。也就是说,不要进行可观察收集,而是进行可观察收集。它使 事情更简单,更容易和更可重用


另一个注意事项:尽量避免使用DataGrid。这让开发者们想把头发扯下来。我将使用ListView推出您自己的网格:

我写了一篇关于MVVM中的撤消/重做的文章。它分为两部分:第一部分介绍了通用版中的撤消/重做,第二部分介绍了如何使用列表:

流程是:用户操作视图->命令虚拟机->命令执行修改模型->模型通知虚拟机更改->虚拟机通知视图更改。 这样,如果从其他源修改模型,它也会刷新视图


还有一个github项目。

我写了一篇关于MVVM中的撤销/重做的文章。它分为两部分:第一部分介绍了通用版中的撤消/重做,第二部分介绍了如何使用列表:

流程是:用户操作视图->命令虚拟机->命令执行修改模型->模型通知虚拟机更改->虚拟机通知视图更改。 这样,如果从其他源修改模型,它也会刷新视图


还有一个github项目。

我怀疑你对DataGrid=我会尝试使用ListView玩游戏。我怀疑你对DataGrid=我会尝试使用ListView玩游戏是正确的。我考虑过这一点,对我的场景来说没问题,但在其他情况下,必须知道chages的发起人会做出正确的反应。例如,与用户操作相比,当模型被某种自动化更改时,我们不需要撤消/重做。我考虑过这一点,这对我的场景来说是可以的,但在其他情况下,必须知道更改的发起人能够做出正确的反应。例如,与用户操作相比,当通过某种自动化更改模型时,我们不需要撤消/重做。