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

发布于 2024-11-19 04:33:10 字数 641 浏览 2 评论 0原文

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

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

  • 左侧部分有一个 UserControl ,里面有一个 TreeView它。
  • 右侧部分有一个 ContentControl,它托管 UserControl,具体取决于 TreeViewUserControl 中选择的项目。

为了解释这个情况,我给你举一个例子。

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

只有当用户单击“文件”菜单中的“保存”时,数据才会被序列化并保存到磁盘。

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

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

还有其他方法吗?

I have a requirement for which i have to implement a 3 Step save functionality

I have a MainView which is divided into two parts:

  • Left Part has a UserControl which has a TreeView inside it.
  • Right Part has a ContentControl which hosts UserControl depending upon the Item selected in the TreeViewUserControl.

To Explain the senario i give you an example.

If i click a leaf Node the Data UserControl Will be populated and the Data of the respective selected TreeView Item is populated for the Model ->ViewModel-> View(UserControl). If the user changes the Data and then saves it it must be saved temporarily and if the user cancels all changes must be discarded. The same behavior should be demonstrated when adding new nodes to the TreeView.

Only when the user clicks Save in the File menu should the data be serialized and saved to disk.

In addition, if the user tries to navigate away, I wish to prevent them from doing so until they either save or cancel their changes.

I am facing problem in saving the temporary state of these Data objects in such senario. I tried using shallow copies but this is not working as its giving only the references of the main Entity (initialized when the file is read).

Is there any other approach?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

谜兔 2024-11-26 04:33:10

你的问题确实与WPF或MVVM没有太大关系。您需要跟踪模型状态的更改,并能够从 ViewModel 查询所有模型的状态,以确定是否应该允许用户离开。

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

我将如何(大致)完成此任务:

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

  • IsDirty { get; 取消编辑
  • ();
  • 接受编辑();

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

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

这对于编码来说可能会变得非常乏味。我确信有一些框架旨在提供此类功能。我只是不知道有什么临时的。

Your question really doesn't have much to do with WPF or MVVM. You need to keep track of changes to your Model's states, and be able to query the states of all Models from your ViewModels to determine if you should allow users to leave.

Unfortunately, the framework doesn't natively support this pattern. You must write it yourself.

How I would (roughly) accomplish this:

Each Model would implement an interface, lets say IDirty. This interface has the following properties/methods:

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

Upon creation, the Model is not dirty (IsDirty == false). As its properties are changed, it becomes Dirty. The original state of all properties is also remembered. If the user cancels, then CancelEdit() is called and the original state is restored. If AcceptEdit() is called, then the original state is overwritten with the current state.

I would also create custom ObservableCollection implementations that would allow me to query the state of all Models contained within to determine if any is dirty. Same for my ViewModels, so the View can bind to the ViewModel's IsDirty property, which queries all collections of Models within the ViewModel. Likewise, calls to CancelEdit and AcceptEdit are chained as well, so you can (for example) call AcceptEdit() on the ViewModel and all Models within will have AcceptEdit called on them.

This can become very tedious to code. I'm sure there are some frameworks out there that are designed to provide this type of functionality. I just don't know of any offhand.

枕头说它不想醒 2024-11-26 04:33:10

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

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

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

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

发生这种情况是因为 TextBox 默认 UpdateSourceTrigger 是 LostFocus,而不是 PropertyChanged。

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

不幸的是,WPF Binding 类没有实现 IsDirty 功能,即使它是它处于完美的位置,可以访问源 (ViewModel) 和目标 (TextBox),并收到所有相关事件的通知。

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

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

If you use the standard WPF Binding approach then it is very hard to achieve robust form handling.

This is because there are 2 types of IsDirty, ViewModel.IsDirty (your responsibility) and Binding.IsDirty (WPF responsibility).

Binding.IsDirty occurs when a TextBox Text value has changed, but not been sent to the Binding Source.

It is possible for ViewModel.IsDirty to be false, while Binding.IsDirty to be true.

This happens because TextBox default UpdateSourceTrigger is LostFocus, not PropertyChanged.

It has to be this way otherwise editing a DateTime (etc.) will fight the user (validation will fail during partial edits and there will be constant reformatting of the user input)

Unfortunately WPF Binding class does not implement IsDirty functionality, even thought it is in a perfect position to do so, it has access to both the Source (ViewModel) and the Target (TextBox) and is notified of all relevant events.

Furthermore the design of the Binding class does not lend itself to being extended with this functionality. IMO It is a "Black Box" and a great example of how not to design software.

My solution is to create my own Binding class and then I can be productive again.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文