【问题标题】:MVVM Application not Restoring State CorrectlyMVVM 应用程序未正确恢复状态
【发布时间】:2014-10-27 07:05:24
【问题描述】:

我已经建立了一个类库,作为一个可以被其他项目继承的 GUI 框架。此应用程序基于项目 WildGemini

我的问题是在使用标准序列化程序恢复 Avalon Dock 的布局时

var layoutSerializer = new XmlLayoutSerializer(manager);

其中manager 是类型DockingManager。经理恢复并清空选项卡。我的猜测是 Caliburn Micro 找不到存储的 ViewModel(名为 HomeViewModel)。但是,我正在努力确认这一点。

我相信我的引导程序是正确的,并且正确设置了 MEF 容器以允许解析外部类型。我已将项目调试到我认为发生此问题的程度,并且在输出窗口中我可以看到发生附加的Attach(Home)(注意,“Home”是HomeViewModel 的显示名称)。但是,我不知道附加过程有什么问题,因为这是由 MEF/Caliburn 处理的。

我真的很想调试这个,想知道是否

  1. 任何人都可以就如何进行调试过程提供任何有见地的建议?
  2. 有人愿意看看解决方案吗?

我已经花了很多时间调试这个没有任何运气,这个问题非常深奥和虚幻,以至于这里的大多数帖子都与我无关。

感谢您的宝贵时间。

【问题讨论】:

  • 一个可以重现该问题的工作示例将不胜感激。
  • 嗨@pushpraj,非常感谢您的回复。这个要死我了!这是项目1drv.ms/1A4v40R 的GUI 部分的链接。它不是最小的,因为我也包含了 packages 文件夹。如果你能帮助我,我愿意为你提供代表。另外,一旦你下载了这个,你能告诉我,这样我就可以锁定它。非常感谢...
  • 如果您构建项目并运行它,您将看到打开了“主页”选项卡。现在,默认情况下,所有Documents 对象或更准确的LayoutItemBase 对象都将其ShouldReopenOnStartup 属性设置为false。但是,如果您在打开“主页”选项卡的情况下关闭应用程序,则会创建 ApplicationState.bin,您将看到 HomeViewModel 被写入打开的文档中。现在,当程序启动备份时,这个项目不应该被恢复,但它是。我的想法是 MED/CaliburnMicro 没有找到该类型...
  • 这会导致空白类型被恢复。我采用这种机制来打开和关闭来自Gemini 的文档,因为以推荐的方式执行还原时存在一些错误。我使用的开局策略应该与双子座的相同,并且双子座的工作正常。这就是为什么我认为这可能是一个解决问题。你觉得你可以看看这个吗?我会在适当的时候为这个问题增加一个赏金。
  • 我已经下载了项目,你可以锁定相同的。让我有时间看看。这里有点晚了,希望我明天上来你不会介意。

标签: wpf mvvm mef caliburn.micro avalondock


【解决方案1】:

如上所述,在查看提供的示例代码后,我了解以下内容

  • HomeViewModel 或者可以说 LayoutItemBase 不应该重新打开,因为 ShouldReopenOnStartup 设置为 false
  • 如果在为 HomeViewModel 打开文档的同时关闭应用程序,它将在下次启动时恢复为空白视图 [不正常]

分析

SaveState 方法正确地遵循了ShouldReopenOnStartup 值并且没有发出HomeViewModel 的状态,但停靠管理器仍在发出文档的元素。

因此,在下次重新启动时,LoadState 没有找到任何存储状态,但由于停靠管理器的布局状态中存在元素而创建了一个窗口

  <LayoutDocument Title="HomePP" IsSelected="True" IsLastFocusedDocument="True" ContentId="d716f824-cfff-4b54-8fd6-2d026a99369a" .../>

您确实尝试使用序列化回调的 e.Cancel 属性来取消事件,但似乎它不应该阻止加载窗口,而只是在不需要时取消事件。

分辨率

所以理想的方法是在保存布局之前关闭不应该恢复的文档

这就是我的做法

ShellViewmodel.cs : Line 279 方法SaveState(string)

更改以下代码

    if (!item.ShouldReopenOnStartup)
        continue;

    if (!item.ShouldReopenOnStartup)
    {
        //this item is not supposed to be restored so close the window before saving layout
        IDocument doc = item as IDocument;
        if (doc != null)
            CloseDocument(doc);
        continue;
    }

【讨论】:

  • 非常感谢您查看此内容。这是一个很好的妥协。我的困惑来自反序列化回调似乎没有正确取消的事实。此外,在加载状态操作期间,空白IDocument 被实例化的位置还不清楚;这不是ShouldReopenOnStartup 被忽略的事实,更多的是为什么恢复的HomeViewModel 是空白的。似乎 MEF 无法解决这个Export。我从 Gemini 继承的这段代码,在这个阶段我可能会重写它以处理我(还)没有问题的错误。
  • 再次感谢您抽出宝贵时间。我将奖励你在适当的时候(格林威治标准时间 13 小时 @ 10:06)所花费的时间......
  • 很高兴能成为您的帮助,同时感谢您的感谢。我还想强调它不是一个空白的 IDocument,而是一个停靠管理器的layout element,它将 IDocument 作为内容托管。这个布局元素确实通过layoutSerializer.Serialize(stream) 存储在应用程序状态文件中,并且当您通过layoutSerializer.Deserialize(stream) 反序列化状态时也会恢复回来。其次,ShouldReopenOnStartup 是来自 gambit 框架的custom property,因此布局管理器可能无法识别。
  • 好的,感谢您的澄清,现在更有意义了。我认为您的解决方案是合理的,我可能会采用。我想这让我感到困惑,因为我从 Gemini 抄袭了这部分代码,并且它适用于 Gemini 项目 - 我陷入了试图找出差异而不是推出我自己的解决方案的困境 -真的很傻。让我复制 Gemini 的东西而不是自己编写的原因是这个项目似乎纠正了 AvalonDock 状态文件的一些众所周知的问题,所以我想为什么不使用它。一切顺利,谢谢...
  • 太好了!如果需要,您可以随时从我的个人资料中找到我。快乐编码:)
猜你喜欢
  • 2016-05-09
  • 1970-01-01
  • 2013-02-24
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多