我刚刚开始使用 MvvmCross,但我没有找到任何关于如何从 ViewModel 执行 UI 代码的信息。
在 Caliburn 上有协程,因此我可以访问视图并将 ui 代码与 viewmodel 代码分开。在我的第一种情况下,我需要从 ViewModel 中的命令打开一个对话框,正确的方法是什么?
现在我正在开发一个 WinRT 应用程序。
谢谢
我刚刚开始使用 MvvmCross,但我没有找到任何关于如何从 ViewModel 执行 UI 代码的信息。
在 Caliburn 上有协程,因此我可以访问视图并将 ui 代码与 viewmodel 代码分开。在我的第一种情况下,我需要从 ViewModel 中的命令打开一个对话框,正确的方法是什么?
现在我正在开发一个 WinRT 应用程序。
谢谢
在 MvvmCross 中对此没有任何硬性/快速规则。
通常,当我需要这样做时,我会使用 Messenger 插件。
此答案假定您使用的是最新的 Alphav3
代码。对于较旧的 vNext 代码,您必须进行一些翻译 - 请参阅下面的注释。
要使用这种方法:
我参考Cirrious.MvvmCross.Plugins.Messenger.dll
了 Core 和 UI 项目。
然后我在 Setup.cs 中的某处(例如 in InitializeLastChance
)添加一行:
Cirrious.MvvmCross.Plugins.Messenger.PluginLoader.Instance.EnsureLoaded();
然后在核心项目中添加一条消息:
public class InputIsNeededMessage : MvxMessage
{
public InputIsNeededMessage(object sender) : base(sender) {}
}
在 ViewModel 中,我可以通过构造函数注入或通过以下方式获取 Messenger:
var messenger = Mvx.Resolve<IMvxMessenger>();
我可以通过以下方式发送消息:
messenger.Publish(new InputIsNeededMessage(this));
在视图中,我可以再次使用 Messenger 并订阅消息:
var messenger = Mvx.Resolve<IMvxMessenger>();
_token = messenger.SubscribeOnMainThread<InputIsNeededMessage>(OnInputIsNeeded);
where_token
必须是成员变量 - 如果不是,则订阅将不会持续存在 - 默认情况下订阅本身很弱(因此您永远不必取消订阅)
以及OnInputIsNeeded
类似的东西在哪里:
private void OnInputIsNeeded(InputIsNeededMessage message)
{
if (message.Sender != ViewModel)
return;
// do stuff here - you are already on the UI thread
}
上面的序列是我通常为“正确代码”所做的
开始使用 Messenger/EventAggregator 可能会感到不舒服 - 我确实需要一段时间才能习惯它 - 但在我习惯了它之后,我现在在任何地方都使用它 - pub/sub 消息解耦对于测试和代码的未来维护(IMO)
作为上述这种方法的替代方案,我有时会采取捷径:
抱歉使用v3
语法 - 但转换即将到来,这就是我现在正在编码的......
要切换回vNext
我认为您可能需要:
IMessenger
而不是IMvxMessenger
BaseMessage
而不是MvxMessage
Subscribe
而不是SubscribeOnMainThread
- 但是您需要自己将消息编组到 UI 线程上。有一种更简单的方法。这是我用于在主线程上执行任何操作的方法:
protected void RunOnUIThread(Action action) {
var dispatcher = Mvx.Resolve<IMvxMainThreadDispatcher>();
dispatcher.RequestMainThreadAction(action);
}
希望能帮助到你。干杯。