ViewModel 的构造函数在导航时再次被调用,因此消息订阅被再次订阅

2023-12-11

我正在使用构建跨平台移动应用程序MvvmCross框架。

由于我想在 ViewModel 之间共享信息,因此我使用内置的方法在 ViewModel 的构造函数内注册通知MvxMessenger.
我们假设一条消息名为ShowAdsMsg,然后 ViewModel 如下所示:

public class AdsViewModel : BaseLookersViewModel, IAdsViewModel
{
    private MvxSubscriptionToken _showAdsMsgToken;

    public AdsViewModel()
    {
        _showAdsMsgToken = MvxMessenger.Subscribe<ShowAdsMsg>(message => onShowAdsNavigation(), MvxReference.Weak);
        MyMessenger.PublishLastMessage();
    }
    private void onShowAdsNavigation()
    {
        //Do Stuff
    }
}

有关MyMessenger thing:
到 ViewModel 的实际导航是从MainViewModel.
因为在导航本身的那一刻AdsViewModel尚不存在,消息发布自MainViewModel无法到达它。
所以,我的想法是天真地“记住”该消息并在新的 ViewModel 准备就绪时发布它。
所以现在导航调用来自MainViewModel看起来像这样:

    private void navigate()
    {
        MyMessenger.RememberMessage(new ShowAdsMsg(this));
        ShowViewModel<AdsViewModel>( );
    }

我现在可以导航到 ViewModel,并且所有通知均已成功捕获。

然而...
当我按下设备上的“后退”按钮并重新导航到同一个 ViewModel 时,
构造函数被再次调用,因此消息订阅重新发生。
结果,当消息到达时onShowAdsNavigation()处理程序被解雇两次!

I found this类似的帖子,讨论如何正确处理 ViewModel 的问题,
但它不包含对我的问题的直接解决方案。

我需要的是一个解决方案。它可以是以下之一:

  1. 想法如何不订阅 ViewModel 的 ctor 上的消息。
  2. 有关如何以及何时正确处置 ViewModel 的指南。
  3. 解释为什么再次调用构造函数以及如何避免这种情况。
  4. 一种完全不同的 ViewModel 信息传递方法。

预先感谢您的帮助!

编辑: 我发现thisSO Answer,基本上回答了上面列表中的第 3 项。 不过,我想知道对于信使问题我应该采取什么方法。

另一个编辑: 我验证了 MvvmCross 教程中存在相同的行为N-05-多页。我只是向 SecondViewModel 添加了一个 ctor,并在每次 BACK+Renavigate 之后在其中点击了一个断点。


解释为什么再次调用构造函数以及如何避免这种情况。

The ctor不会对同一个对象调用两次 - 相反,可能发生的是一个新的View和一个新的ViewModel每次都会被创建。

默认情况下我would期望在每个平台上的每个前向导航上创建一个新的 ViewModel。

默认情况下我不会预计这种情况会在 WindowsPhone 上的后退按钮期间发生 - 对于我的测试用例,这种情况不会发生 - 但如果出现以下情况,则可能会发生:

  • WindowsPhone 会从内存中删除您的第一个页面(及其 ViewModel) - 我想如果您的应用程序已被逻辑删除或您正在使用自定义 RootFrame,则可能会发生这种情况 - 但我不认为默认情况下会发生这种情况。
  • 您以某种方式将第一页中的 ViewModel (DataContext) 设为 null

如果没有看到更多代码,我无法再猜测为什么会发生这种情况。


我个人建议您更深入地了解为什么会在 Back 期间看到创建新的 ViewModel,但如果您只是想要快速修复,那么您可以考虑覆盖 MvvmCross 中的 ViewModelLocator - 请参阅MvvmCross:ShowViewModel 是否总是构造新实例?


请注意,在 WindowsStore 上,我预计会发生这种情况 - 默认情况下,WindowsStore 不会将后台堆栈中的页面保存在内存中 - 但您可以通过设置来覆盖它NavigationCacheMode = NavigationCacheMode.Enabled;如果你需要。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ViewModel 的构造函数在导航时再次被调用,因此消息订阅被再次订阅 的相关文章

  • GLKit的GLKMatrix“列专业”如何?

    前提A 当谈论线性存储器中的 列主 矩阵时 列被一个接一个地指定 使得存储器中的前 4 个条目对应于矩阵中的第一列 另一方面 行主 矩阵被理解为依次指定行 以便内存中的前 4 个条目指定矩阵的第一行 A GLKMatrix4看起来像这样 u
  • 为什么两个不同的 Base64 字符串的转换会返回相等的字节数组?

    我想知道为什么从 base64 字符串转换会为不同的字符串返回相同的字节数组 const string s1 dg const string s2 dq byte a1 Convert FromBase64String s1 byte a2
  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • 使用 WebClient 时出现 System.Net.WebException:无法创建 SSL/TLS 安全通道

    当我执行以下代码时 System Net ServicePointManager ServerCertificateValidationCallback sender certificate chain errors gt return t
  • C++ OpenSSL 导出私钥

    到目前为止 我成功地使用了 SSL 但遇到了令人困惑的障碍 我生成了 RSA 密钥对 之前使用 PEM write bio RSAPrivateKey 来导出它们 然而 手册页声称该格式已经过时 实际上它看起来与通常的 PEM 格式不同 相
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • WCF 中 SOAP 消息的数字签名

    我在 4 0 中有一个 WCF 服务 我需要向 SOAP 响应添加数字签名 我不太确定实际上应该如何完成 我相信响应应该类似于下面的链接中显示的内容 https spaces internet2 edu display ISWG Signe
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 如何从两个不同的项目中获取文件夹的相对路径

    我有两个项目和一个共享库 用于从此文件夹加载图像 C MainProject Project1 Images 项目1的文件夹 C MainProject Project1 Files Bin x86 Debug 其中有project1 ex
  • 为什么编译时浮点计算可能不会得到与运行时计算相同的结果?

    In the speaker mentioned Compile time floating point calculations might not have the same results as runtime calculation
  • cmake 将标头包含到每个源文件中

    其实我有一个简单的问题 但找不到答案 也许你可以给我指一个副本 所以 问题是 是否可以告诉 cmake 指示编译器在每个源文件的开头自动包含一些头文件 这样就不需要放置 include foo h 了 谢谢 CMake 没有针对此特定用例的
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK

随机推荐

  • 如何使用 log4j2 记录 CXF Web 服务请求?

    我想记录所有传入和传出CXF对特定日志文件的请求 但我通过以下配置得到的只是控制台输出 这里有什么问题吗 log4j2 xml
  • 如何停用浏览器中的缓存?

    例如 如果您退出雅虎邮件 然后单击后退按钮 它不会加载最后一页 而是将您重定向到登录页面 我必须用我的 PHP 代码来完成此操作 我正在使用 CodeIgniter 有些朋友告诉我禁用缓存 但这将是一件坏事 因为我的系统中有很多图像 每次都
  • 为什么 Safari 会重复 GET 请求,而 Chrome 却不会?

    Update TL DR 这可能是 Safari 和 或 Webkit 中的错误 更长的 TL DR 在 Safari 中 使用 Fetch API 发出 GET 请求后 当页面重新加载时 Safari 会自动 无意中 重新运行该请求即使发
  • 位串最近邻搜索

    我有数十万个长度为 32 位的稀疏位串 我想对它们进行最近邻搜索 并且查找性能至关重要 我一直在阅读各种算法 但它们似乎针对文本字符串而不是二进制字符串 我认为局部敏感散列或频谱散列似乎都是不错的选择 或者我可以考虑压缩 这些中的任何一个都
  • DataGridView CellPaint 不能完全在滚动上工作

    第一次发帖 但浏览了很长时间 所以这是我的问题 基本上我有一个用于与用户交互的 datagridview 在所有行中 都有一个 信息 按钮 它会产生一种错觉 即它在其下方添加了另一行 并合并了所有单元格 整个行中的一个长单元格 并绘制了描述
  • 在python中计算矩形的质心

    我想计算矩形的质心 矩形的坐标如下 co ord 601 1006 604 1009 xmin ymin xmax ymax 有人可以指出一个简单的方法吗 谢谢 对角矩形的质心 x1 y1 and x2 y2 位于该矩形的中心 x1 x2
  • 将标头添加到 @aspnet/signalr Javascript 客户端

    我正在使用 aspnet signalr 官方 Javascript 客户端这个npm包 我想知道是否有办法将Header配置添加到客户端连接头 我如何建立联系 let connection new signalR HubConnectio
  • Scrapy xpath不提取包含特殊字符<%=的div

    我是 Scrapy 新手 我正在尝试从以下 URL 中提取 h2 文本 https www tysonprop co za agents 我有两个问题 我的 xpath 可以访问 script 元素 但无法找到 script 标记内的 h2
  • xml 格式文件和标识列的 bcp 导入错误

    我在 SQL Server 中创建了一个表 如下所示 CREATE TABLE dbo myId smallint IDENTITY 1 1 NOT NULL name nchar 10 NOT NULL value int NOT NUL
  • Thymeleaf - 将
    附加到输入标签

    我正在尝试附加一个 br 在表单中的每个输入行之后 但 Thymeleaf 一直给我解析错误 这是我遇到问题的代码片段
  • 不花钱在生产环境进行内购测试

    我有一个 iOS 应用程序 即将在 App Store 上发布 我想在生产环境中测试应用内购买 如何测试尚未发布的生产应用程序的应用内购买 答案是不 对于尚未在 App Store 上发布的应用程序 您只能在沙盒环境中测试您的 IAP 项目
  • 在 umbraco 中分配主机名

    我正在使用 umbraco cms 设置 af 多语言页面 我的内容结构如下所示 Content da 丹麦子页面 1 丹麦子页面 2 en 英文子页1 英文子页2 我希望路由是这样的 http mysite dk应该去http mysit
  • 如何删除/忽略触摸设备上的 :hover css 样式

    我想忽略一切 hover如果用户通过触摸设备访问我们的网站 则 CSS 声明 因为 hoverCSS 没有意义 如果平板电脑在单击 点击时触发它 它甚至会令人不安 因为它可能会一直粘到元素失去焦点 说实话 我不知道为什么触摸设备感觉需要触发
  • Git - 浏览远程存储库

    我工作中遇到一个小问题 我们将所有不同的项目提交到不同的远程存储库 有时人们会对他们在凌晨 4 点喝咖啡时创建的名称感到困惑 所以我的问题是 有没有办法浏览远程存储库以列出所有分支 任何帮助是极大的赞赏 要仅列出远程分支 请首先获取 以确保
  • SDL 2.0 不会初始化。错误:“无法连接到 Mir 服务器”

    我正在运行 Ubuntu 14 04 并使用 Eclipse CDT 在我的程序中 我尝试初始化 SDL 如果它没有初始化 则输出错误 但 SDL GetError 返回 无法连接到 Mir 服务器 我确信 SDL 已正确安装 因为我可以在
  • 优雅加载网页的技巧?

    我有一个网页 其中有很多内容 当页面使用 jQuery javascript 处于各种状态时 这些内容会被隐藏 显示 样式化 我遇到了一个问题 在页面的初始加载时 我的所有内容都以一种可怕的方式显示了几分之一秒 然后所有内容都被样式化 隐藏
  • 如何在Polymer中动态追加一个元素到dom-if?

    我的目标是将一个元素附加到现有的dom if动态地 问题是 追加后我可以在 DOM 三个中看到追加的元素 但它永远不会做出反应condition并始终隐藏
  • 可以传递给 Wininet 函数 HttpOpenRequest 的最大 URL 长度是多少?

    可以传递给 Wininet 函数 HttpOpenRequest 的最大 URL 长度是多少 WinInet h 中有一些最大长度常量 maximum field lengths arbitrary define INTERNET MAX
  • 行延续在 VBA 中不适用于 2D 数组构造

    在下面的子例程中 定义二维数组似乎不适用于行延续 TestArray1 按预期初始化 但是当我添加行继续时我收到消息 编译错误 缺少右括号 实际上 我不确定英语的确切措辞 用德语执行此操作 在德语中 错误消息是 Fehler beim Ko
  • ViewModel 的构造函数在导航时再次被调用,因此消息订阅被再次订阅

    我正在使用构建跨平台移动应用程序MvvmCross框架 由于我想在 ViewModel 之间共享信息 因此我使用内置的方法在 ViewModel 的构造函数内注册通知MvxMessenger 我们假设一条消息名为ShowAdsMsg 然后