WPF UI 不刷新

WPF UI not refreshing

我在 wpf / mvvm 项目中刷新 UI 时遇到问题。

当我注销时,在 UI 上有一个操作来显示 "waiting" 对象,然后执行一个很长的过程。

我提供的所有代码都不完整

private void btnPower_Click(object sender, RoutedEventArgs e)
{
      // IHM changes
      btnRightMenuShow.IsEnabled = false;
      btnRightMenuShow.Visibility = Visibility.Hidden;
      StationWindowViewModel stnWindowVM = (StationWindowViewModel)DataContext;
      stnWindowVM.ProgressMode = LoadingProcessViewModel.ProgressMode.Sending;

      // PRocess
      if (stnWindowVM.PowerOffCmd.CanExecute(null))
      {
          stnWindowVM.PowerOffCmd.Execute(null);
      }
}

像这样,ihm 就像在过程中冻结一样,在应用程序结束之前从不刷新()。

我首先尝试使用像

这样的后台工作者
private void btnPower_Click(object sender, RoutedEventArgs e)
{
      // IHM changes
      btnRightMenuShow.IsEnabled = false;
      btnRightMenuShow.Visibility = Visibility.Hidden;
      StationWindowViewModel stnWindowVM = (StationWindowViewModel)DataContext;
      stnWindowVM.ProgressMode = LoadingProcessViewModel.ProgressMode.Sending;

      // PRocess
      powerOffWorker.RunWorkerAsync(stnWindowVM);
}

private void powerOffWorker_DoWork(object Sender, System.ComponentModel.DoWorkEventArgs e)
{
      if (stnWindowVM.PowerOffCmd.CanExecute(null))
      {
          stnWindowVM.PowerOffCmd.Execute(null);
      }
}

在这种情况下,IHM 已刷新,但我有一些线程错误,一些代码试图访问主进程上父线程创建的对象(调用线程无法访问该对象,因为另一个线程拥有它)

所以我尝试使用像

这样的调度程序
private void btnPower_Click(object sender, RoutedEventArgs e)
{
      // IHM changes
      btnRightMenuShow.IsEnabled = false;
      btnRightMenuShow.Visibility = Visibility.Hidden;
      StationWindowViewModel stnWindowVM = (StationWindowViewModel)DataContext;
      stnWindowVM.ProgressMode = LoadingProcessViewModel.ProgressMode.Sending;

      // PRocess
      this.Dispatcher.Invoke(new Action(() =>
      {
          if (stnWindowVM.PowerOffCmd.CanExecute(null))
          {
              stnWindowVM.PowerOffCmd.Execute(null);
          }
      }));
}

我也尝试在 backgrounworker 中使用调度程序,但是对于那些调度程序,我在调用线程方面不再有问题,但是 UI 没有更新。

编辑

这是我对 async/await 实现的测试

private void btnPower_Click(object sender, RoutedEventArgs e)
{
  // IHM changes
  btnRightMenuShow.IsEnabled = false;
  btnRightMenuShow.Visibility = Visibility.Hidden;
  StationWindowViewModel stnWindowVM = (StationWindowViewModel)DataContext;
  stnWindowVM.ProgressMode = LoadingProcessViewModel.ProgressMode.Sending;

  // PRocess
  PowerOffAsync(stnWindowVM);
}

private async void PowerOffAsync(StationWindowViewModel stnWindowVM)
{
    await Task.Run(() =>
    {
        if (stnWindowVM.PowerOffCmd.CanExecute(null))
         {
            stnWindowVM.PowerOffCmd.Execute(null);
        }
    });
}

在 PowerOffCmd 进程中,对对象(如列表)进行了一些操作,导致调用线程出错...

您的问题是您尝试在等待调用中调用调度程序,而不是在您需要处理的地方调用它 UI。

基本上,如果你这样做

await Task.Run(() =>
{
    this.Dispatcher.Invoke(new Action(() =>
    {
        if (stnWindowVM.PowerOffCmd.CanExecute(null))
        {
            stnWindowVM.PowerOffCmd.Execute(null);
        }
    }));
});

你做错了,因为你一直在 UI 线程上处理你的异步工作。

您可以尝试的一种变通方法是在您的 PowerOffCmd 中调用调度程序,它会给您错误。这样,除了您需要在 UI 线程上工作(例如修改控件)之外的所有内容都将在单独的线程上执行,这将确保您 UI 保持响应。