从对话框的 VM 外部更新 Caliburn Micro 中的模态对话框

Posted

技术标签:

【中文标题】从对话框的 VM 外部更新 Caliburn Micro 中的模态对话框【英文标题】:Update modal dialog in Caliburn Micro from outside the dialog's VM 【发布时间】:2021-12-11 23:38:21 【问题描述】:

我遇到以下情况:我正在尝试将文件加载到应用程序中(这是一个使用 Caliburn Micro 的基于 C# 的 WPF 应用程序)。

这个文件的性质并不重要,但加载过程包含许多步骤,对于大文件,可能需要一段时间才能完成。

我想要做的是在我的应用程序中显示一个模态对话框,该对话框在加载过程开始时显示,最后关闭并在加载过程中由应用程序更新,以便对话框中的文本反映应用程序已到达加载过程中。

我已经通过在对 windowmanager.ShowDialog() 的调用中传入关联的视图模型来显示视图,但是没有任何反应。我只能假设这是因为对话框可能是同步显示的,因此永远不会到达完成加载和更新对话框的后续调用。

本质上这是我目前正在尝试的事情(VM 有一个在视图中使用的消息字符串属性):

windowManager.ShowDialog(ProgressDialogVM);

doSomething();
ProgressDialogVM.Message = "Step 2";
doSomethingElse();
ProgressDialogVM.Message = "Step 3";
doSomethingElseAgain();
ProgressDialogVM.Message = "Step 4";

ProgressDialogVM.TryClose();

对话框 VM 中的属性如下所示:

private string message = "";
public string Message

    get
    
        return message;
    
    set
    
        if (value != message)
        
            message = value;
            NotifyOfPropertyChange(nameof(message));
        
    

最后是用于文本框的 XAML,以防此处相关:

<TextBlock Grid.Row="1" Text="Binding Path=Message, UpdateSourceTrigger=PropertyChanged" />

任何关于如何做到这一点的想法将不胜感激。

编辑 我已经到了可以显示窗口并让代码执行的地步了。我什至可以在视图模型中成功设置属性并在窗口中显示初始值。然而,现在的问题是该值虽然可以设置,但并未在相应的视图中更新。它非常高兴地显示了初始值,但在那之后没有任何变化。

因此,在窗口下方的测试示例中,窗口将显示“步骤 0”,但不会更新为显示“步骤 1”。

ProgressDialogViewModel ProgressDialogVM = new ProgressDialogViewModel();  
ProgressDialogVM.Message = "Step 0";
windowManager.ShowWindow(ProgressDialogVM, null, null);
ProgressDialogVM.Message = "Step 1";

【问题讨论】:

什么是ProgressDialogVM?它是否继承自MessageBox 它继承自 Screen。 MessageBox 似乎是一个密封类。 【参考方案1】:

WindowManager.ShowDialog() 打开一个模态窗口,这就是为什么它会阻止主/父窗口中的进一步操作,直到模态窗口关闭。这就是为什么在打开 ProgressDialogVM 时无法执行第一个代码示例中的后续步骤的原因。

在第二种情况下,您使用了WindowManager.ShowWindow,它打开了一个非模态窗口。这允许在主/父窗口中进一步执行代码。但是,看起来后续操作是同步的,因此 UI 线程无法用于在 ProgressDialogVM 上进行 UI 更新。

你可以做的是确保像doSomethingElse这样的中间操作是异步的。

progressDialogVm.Message = "State 01";
_windowManager.ShowWindow(progressDialogVm,null,null);
await DoSomething();
progressDialogVm.Message = "State 02";
await DoSomethingElse();

这将确保 ProgressDialog 中的消息文本根据需要更新。

【讨论】:

以上是关于从对话框的 VM 外部更新 Caliburn Micro 中的模态对话框的主要内容,如果未能解决你的问题,请参考以下文章

Caliburn.Micro框架之Bindings

将UserControl绑定到ViewModel(Caliburn Micro WPF)

如何将 ValueConverter 应用于基于约定的 Caliburn.Micro 绑定示例?

在 C# Caliburn Micro WPF 中异步和等待获取 HttpRequest 时更新 ProgressBar

从0到1:使用Caliburn.Micro(WPF和MVVM)开发简单的计算器

您可以从 Google Compute VM 实例中获取外部 IP 地址吗?