保存和取消WPF应用程序中的更改时出现问题

时间:2011-07-08 05:38:26

标签: .net wpf mvvm savestate

我有一个要求,我必须实现3步保存功能

我有一个MainView,它分为两部分:

  • 左侧部分有UserControl,里面有TreeView
  • 根据ContentControl中选择的项目,右侧部分有一个UserControl来托管TreeViewUserControl

为了解释一下,我给你举个例子。

如果我单击一个叶节点,将填充数据用户控件,并为模型填充相应选定TreeView项的数据 - > ViewModel->查看(用户控件)。如果用户更改数据然后保存,则必须保存暂时,如果用户取消,则必须丢弃所有更改。将新节点添加到TreeView时,应该演示相同的行为。

仅当用户在“文件”菜单中单击“保存”时,才应将数据序列化并保存到磁盘。

此外,如果用户试图离开,我希望阻止他们这样做,直到他们保存或取消他们的更改。

我在这样的senario中保存这些Data对象的临时状态时遇到问题。我尝试使用浅拷贝,但这不起作用,因为它只提供主要实体的引用(在读取文件时初始化)。

还有其他方法吗?

2 个答案:

答案 0 :(得分:0)

你的问题与WPF或MVVM没什么关系。您需要跟踪模型状态的变化,并能够从ViewModel查询所有模型的状态,以确定是否允许用户离开。

不幸的是,该框架本身并不支持这种模式。你必须自己写。

我(大致)如何做到这一点:

每个模型都会实现一个接口,比方说IDirty。此接口具有以下属性/方法:

  • IsDirty {get; }
  • 的CancelEdit();
  • AcceptEdit();

创建后,模型不脏(IsDirty == false)。随着它的属性发生变化,它变得很脏。所有属性的原始状态也会被记住。如果用户取消,则调用CancelEdit()并恢复原始状态。如果调用AcceptEdit(),则原始状态将被当前状态覆盖。

我还会创建自定义ObservableCollection实现,这些实现允许我查询其中包含的所有模型的状态,以确定是否有任何脏。对于我的ViewModel也是如此,因此View可以绑定到ViewModel的IsDirty属性,该属性查询ViewModel中所有模型集合。同样,对CancelEditAcceptEdit的调用也会被链接,因此您可以(例如)在ViewModel上调用AcceptEdit(),并且其中的所有模型都会调用AcceptEdit

这对代码来说可能变得非常繁琐。我确信有一些旨在提供此类功能的框架。我只是不知道有任何副手。

答案 1 :(得分:0)

如果使用标准的WPF绑定方法,那么很难实现健壮的表单处理。

这是因为有两种类型的IsDirty,ViewModel.IsDirty(您的责任)和Binding.IsDirty(WPF责任)。

当TextBox文本值发生更改但未发送到绑定源时,会发生Binding.IsDirty。

ViewModel.IsDirty可能为false,而Binding.IsDirty为true。

这是因为TextBox默认的UpdateSourceTrigger是LostFocus,而不是PropertyChanged。

必须采用这种方式,否则编辑DateTime(等)将对用户起作用(部分编辑期间验证将失败,并且将不断重新格式化用户输入)

不幸的是,WPF Binding类没有实现IsDirty功能,即使它认为它处于完美的位置,它也可以访问Source(ViewModel)和Target(TextBox),并被通知所有相关事件。 / p>

此外,Binding类的设计不适合使用此功能进行扩展。 IMO这是一个“黑匣子”,也是如何不设计软件的一个很好的例子。

我的解决方案是创建自己的Binding类,然后再次提高效率。