有一个类PersonVm表示一个人的信息:
public class PersonVm : BaseViewModel
{
private string _name;
public string Name
{
get {return _name; }
set
{
_name = value;
RaisePropertyChanged();
}
}
}
该类PersonManager是人员的集合,允许您添加/删除人员,以及通过以下方式回滚这些更改UndoRedoService:
public class PersonManager : BaseViewModel
{
public ObservableCollection<Person> Persons {get;set;}
public UndoRedoService UndoRedoService {get;set;} = new UndoRedoService();
}
我还想回滚PersonVm. 可以PropertyChanged为所有人订阅事件并接收发生更改的属性的名称、当前值和新值。
但是在这种情况下,有必要通过反射回滚更改 - 按名称搜索所需的属性并进行更改。这不是一个非常快速的方法。
有可能做一些不同的事情吗?
我扩展了基类
ViewModel以保留更改的历史记录。我有一个测试示例,所以像这样,你很可能需要两个类——有历史和没有历史,这样你就可以从一个或另一个继承。最好有一个包含类及其属性列表的列表,应该保留其更改历史,甚至可以组成一个自定义属性。
我有这样的课:
我添加了以下功能:
现在让我们将 save 添加到方法中
Set<T>:请注意,该解决方案不是线程安全的,但不是必需的,因为 您应该只在 GUI 线程上更新 VM 属性
此处使用以下命令实现:
好吧,一个使用示例:
表现:
添加属性!
创建一个属性类:
在方法的开头,
Vm.SaveHistory添加一个属性是否存在的检查:一切!现在将这个属性附加到所需的属性就足够了:
而且,瞧,故事只是根据指定的属性!
由于您自己执行更改的“回滚”非常繁琐。使用现成的解决方案更容易。开箱即用提供此功能的一个 WPF 框架是Catel。
以下是此类应用程序的一个简单示例:
1)创建一个新项目:
File - New - Project... - WpfApplication.2)安装卡特。
3) 在项目中,我们从以下文件夹创建标准结构:Models、ViewModels、Views。
4) 在Models文件夹中,创建一个类User,代表我们的模型,它将只包含几个属性Name和LastName并从ModelBase继承它。
5)接下来,在Views文件夹中,创建我们的View,我们称之为MainView,它的标记如下所示。请注意,窗口类型是
catel:Window.6) 在ViewModels文件夹中,为我们的MainView创建一个ViewModel。我们称之为MainViewModel。
7)创建一个视图来编辑我们的用户,它将是下一个。请注意,窗口类型是
catel:DataWindow.8)和它的ViewModel:
9) 原则上,就是这样,在解决方案资源管理器中,我们的项目现在看起来像这样:
10) 现在如果您运行应用程序,在 DataGrid 中选择一个用户并开始对其进行编辑,然后单击“ 取消”按钮,所有更改都将被取消。
PS 如果您不想使用 Catel 的 DP 使用这种繁琐的语法怎么办?
选项1
安装 Catel.Fody
在这种情况下, DP的必要代码将通过覆盖IL自动生成,之后在ViewModel中编写如下代码就足够了:
选项 2
使用代码片段