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 保持响应。
我在 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 保持响应。