C# 在方法完成之前,如何从ViewModel中的方法更新UI?

C# 在方法完成之前,如何从ViewModel中的方法更新UI?,c#,wpf,xaml,user-interface,mvvm,C#,Wpf,Xaml,User Interface,Mvvm,我有一个MainWindow.xaml,其中填充了UserControls。我在MainWindow.xaml中有一个控件,它有一个按钮。该按钮绑定到MyViewModel.cs中的以下命令: public ICommand MyCommand { get { return Get(() => MyCommand, () => new RelayCommand(ExecuteMyCommand, CanExecu

我有一个MainWindow.xaml,其中填充了UserControls。我在MainWindow.xaml中有一个控件,它有一个按钮。该按钮绑定到MyViewModel.cs中的以下命令:

    public ICommand MyCommand
    {
        get
        {
            return Get(() => MyCommand, () => new RelayCommand(ExecuteMyCommand, CanExecuteMyCommand));
        }
    }

    public void ExecuteMyCommand()
    {
        Messenger.Default.Send(new NotificationMessage(this, MainWindowMessageBus.ShowPopup1), MainWindowMessageBus.Token);
        Method1();
        Messenger.Default.Send(new NotificationMessage(this, MainWindowMessageBus.ShowPopup2), MainWindowMessageBus.Token);
        Method2();
    }

    public bool CanExecuteInsertBedCommand()
    {
        return true;
    }
Method1()和Method2()分别执行大约5秒的代码。信使正在向codebehind MainWindow.xaml.cs发送消息:

    Popup1 popup1;
    Popup2 popup2;

    private void NotificationMessageReceived(NotificationMessage msg)
    {
        switch(msg.Notification)
        {
            case MainWindowMessageBus.ShowPopup1:
                popup1 = new Popup1();
                ControlContainer.Children.Add(popup1);
                break;
            case MainWindowMessageBus.ShowPopup2:
                // Remove popup1
                ControlContainer.Children.Remove(popup1);
                popup1 = null;
                // Add popup2
                popup2 = new Popup2();
                ControlContainer.Children.Add(popup2);
                break;
            default:
                break;
        }
    }
预期结果:按my按钮后,Popup1立即显示并在Method1()执行时停留在窗口中。然后,Popup2替换窗口中的Popup1,并执行Method2()

实际结果:按下“我的”按钮后,UI中什么也没有发生。Method1()和Method2()按预期执行,在它们都运行后(~10秒),将显示Popup2。我从来没见过弹出窗口

我尝试了两种线程/异步方法,但都不起作用。如何让ExecuteMyCommand()在UI运行时更新它

编辑

好吧,我不能回答我自己的问题,因为某些原因。我不认为这个问题是指定线程的重复,因为这意味着我已经知道我需要在后台运行Method1(),但我没有。不管怎样,我改变的是:

public async void ExecuteMyCommand()
        {
            Messenger.Default.Send(new NotificationMessage(this, MainWindowMessageBus.ShowPopup1), MainWindowMessageBus.Token);
            await Task.Run(() =>
            {
                Method1();
            });
            Messenger.Default.Send(new NotificationMessage(this, MainWindowMessageBus.ShowPopup2), MainWindowMessageBus.Token);
            Method2();
        }

不要调用在UI线程中花费很多时间的方法

您可以尝试创建一个自定义窗口。 在这里,您可以显示用户的所有自定义信息。 由于您的方法需要花费一些时间,您可以添加一个取消按钮作为示例。 还可以添加进度条。当一个方法需要时间时,了解系统的状态是很好的

试试这个,当你按下你的按钮->调用一个命令来创建一个线程

在您的命令中:

void Command()`
{
    // run a thread, create a window and show it
    // you can declare the thread outside if you want use something like join
    Thread threadExecute = new Thread(Execute);
    w = new WinTest();
    w.Topmost = true;
    w.Show();
    threadExecute.Start();
}

// Call when your thread terminated
void finish()
{
    w.Close();
}

void Execute()
{
    // Your big method 1
    // Change the window information
    // big method 2
    this.Dispatcher.Invoke( finish );
}

您在UI线程中执行工作,因此UI线程被您的工作占用,不响应更改和更新自身。您必须在后台线程中执行代码。长时间运行的操作不应在UI线程中执行。使用例如
Task.Run()
。然后,您可以等待任务并根据需要交错UI更新。有关示例,请参见标记的副本。谢谢!我是C#/WPF新手,没有将主线程看作UI线程。我的大多数尝试都是将Messenger发送到另一个线程,但现在很明显,为什么这样做没有意义。一旦我更新了我的代码,我会发布我自己的答案,这样这个问题对某人仍然有用。