如何在 Model-View-ViewModel 架构中从模型方法的中间清晰地获取用户输入?

7
我正在编写一个应用程序,它监听网络连接。当一些数据到达时,它会回复并根据接收到的数据,在回复之前可能需要向用户询问(显示对话框)。
在M-V-VM架构中,如果我需要根据接收到的数据更新GUI,那么事件和绑定到可观察集合是很好的选择,但如果我实际上需要用户的答案才能回复呢?
更糟糕的是,我想要同步完成这个操作,因为我希望我的回复算法只存在于一个地方,而不是分成多个回调函数,责任不明确。
简单来说,就像这样:
HandleMessage(Message msg){
    string reply;
    if (msg.type == 1) {
        reply = ...
    } else {
        string question = msg...
        reply = ShowModalDialog(question); // MVVM violation!
    }
    sender.Send(reply);
}

但我不想从模型中调用视图或视图模型,因为模型需要可重用和可测试性 - 我不希望在每个测试运行中弹出对话框,这将违反MVVM!没有事件(据我所知,它们只是单向的,并且没有回溯渠道来获取事件源的答复)或数据绑定,因为它会是异步的。
这可行吗?这是我问过几位测试驱动开发倡导者的问题,到目前为止,我还没有得到实际可用的答案。然而,在处理过程中需要一些额外的输入是相当常见的。
谢谢!
编辑:这是应用程序逻辑,因此它显然属于模型,即使在这种情况下不是,我也想知道当我真正需要用户在模型业务逻辑例程中间输入时的解决方案。
3个回答

4
这是 MVVM 无法单独解决的问题之一。一个解决方案是使用服务来查询用户,然后让 ViewModel 使用该服务。
在我的项目中,我们使用 PRISM,除了提供服务框架外,还提供其他工具来使 GUI 开发更加容易。 这里 是 PRISM 中服务如何工作的介绍。
因此,在您的情况下,我会创建某种 IOC,向其注册查询服务,然后在 ViewModel 中传递 IOC,然后使用 IOC 获取查询服务,并使用它来查询用户。需要更多工作吗?当然。但这意味着您可以通过简单地在 IOC 中替换它来使用另一种实现来测试查询服务。
MVVM + 服务 = 终极力量!

谢谢,这听起来是一个干净的解决方案,我会阅读链接(感谢您提供链接!) - Tomáš Kafka

1

我不确定这个想法是否严格遵循MVVM的原则,但是...我会将对话框功能封装为一个服务(通过接口引用)。服务的实现应该在UI层中,但是为了测试目的,你可以只是“模拟”接口。


0

实际上,并不是所有的内容都应该放在应用逻辑中。

看起来你有两个不同的“视图”。一个是初始视图(通过网络传入的数据),另一个是确认对话框。

模型需要确定需要显示新视图,向视图发出信号以显示它,然后稍后响应该视图的输入。

不要试图一步完成所有操作。


我同意第一条评论 - 是的,初始视图只是服务的控制台日志窗口,数据输入对话框可以被视为另一个视图。然而,模型是由算法驱动的,我觉得将一个算法分成异步调用UI的部分非常疯狂 - 在某些情况下,这实际上并不可行。此外,从可维护性的角度来看,将算法放在一个方法中要好得多。因此,对GUI的调用必须是同步的。 - Tomáš Kafka
我完全理解你的意思。我曾经在一些非常恼人的地方使用状态机。虽然我知道你不想去那里,但很有可能你会不得不去。如果不需要,那太好了,但你可能需要考虑一下——这可能是你最终要做的事情。对话框通常意味着释放线程。不过,我不会反对你的观点,认为这很疯狂 :) - Bill K

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接