C# 如何在MVVM中强制更新UI?
好吧,让我试着解释一下 我有一个可以触发某种扫描过程的应用程序。这个扫描过程会启动(只是一个数字)10个后台工作人员来做一些事情。5秒钟后(再次,仅仅是一个数字),我想C# 如何在MVVM中强制更新UI?,c#,wpf,mvvm-light,dispatcher,C#,Wpf,Mvvm Light,Dispatcher,好吧,让我试着解释一下 我有一个可以触发某种扫描过程的应用程序。这个扫描过程会启动(只是一个数字)10个后台工作人员来做一些事情。5秒钟后(再次,仅仅是一个数字),我想 杀死所有后台工作人员(为此我使用CancelAsync) 用我从他们那里得到的数据做一些计算 更新UI以显示数据,并启用一些按钮(这些按钮通过名为PerformUpdateCommand的ViewModel命令绑定,它们具有isperformUpdateLowed的CanExecute属性。isperformUpdateLow
- 杀死所有后台工作人员(为此我使用CancelAsync)
- 用我从他们那里得到的数据做一些计算
- 更新UI以显示数据,并启用一些按钮(这些按钮通过名为
的PerformUpdateCommand
命令绑定,它们具有ViewModel
的isperformUpdateLowed
属性。CanExecute
依赖属性在我的任务完成时设置isperformUpdateLowed
- 触发后台工作程序后,以5秒的间隔启动调度程序计时器
- 当调度程序发出“滴答声”时,我计算数据并将属性
设置为true或falseIsPerformUpdateAllowed
IsPerformUpdateAllowed
属性也被设置为true。此外,当我按下按钮(处于禁用状态)后,它将被启用
因此,尽管我正确设置了dependency属性,但UI不会对此更改做出反应
有人知道为什么吗?有趣的是,我还将UI中的一些文本设置为标签-这些文本被正确更新。只是告诉命令CanExecute
的属性没有触发UI更新
定时器初始化代码
_scanTimer = new DispatcherTimer();
_scanTimer.Interval = new TimeSpan(0, 0, 0, 3);
_scanTimer.Tick += delegate
{
// After the timer has elapsed (some time passed), cancel all scans and update the result
_scanTimer.Stop();
UpdateScanResults();
CancelNormalScans(false);
};
_scanTimer.Start();
编码命令如何绑定到WPF元素(按钮实际上是一个超链接):
代码实际上依赖于两个依赖属性IsScannedDeviceAvailable而不是IsUpdateInProgress。这两个属性都是依赖属性
更新:我刚读到CanExecute属性的绑定只有一次。如果你想重新验证它,你需要在命令上调用RaiseCanExecuteChanged。这是可行的,但有点麻烦,因为现在每当两个属性中的一个发生更改时,我都需要手动调用它。实际上我想自动处理它。一个关于如何更容易地实现这一点,你有什么想法吗?难道没有一些方法可以在CanExecute和属性之间进行某种单向绑定吗?在你的VM调用上,无论何时设置IsCannedDeviceAvailable/IsUpdateInProgress,RaiseCanceChanged都可以。或者我个人最喜欢的方法是创建你自己的
ICommand
实现,因为它很漂亮反正很简单
public class FooCommand : ICommand
{
private bool _canExecute;
private Action _delegate;
public event EventHandler CanExecuteChanged;
public new bool CanExecute
{
get
{
return _canExecute;
}
set
{
_canExecute = value;
if(CanExecuteChanged != null)
CanExecuteChanged();
}
}
public void Execute(object parameter)
{
_delegate();
}
bool ICommand.CanExecute()
{
return CanExecute;
}
public FooCommand(Action action)
{
_delegate = action;
}
}
如果根据属性触发
命令.CanExecute()
中的更改,也可以调用命令管理器.invalidateRequestSuggested()
强制执行CanExecute()
待重新评估。您的iPerformUpdateAllowedDependencyProperty依赖于什么?您的ICommands没有引发CanExercuteChanged事件。@Aron:有没有比手动调用RaiseCanceTechChanged更好的方法?@TomL。这是最好的方法。对于视图模型操作,可以假定您知道应用程序何时准备好进行command输入。谢谢,这应该可以。但是,我实际上想用另一种方式对整个过程进行编码。一旦一个命令的所有条件都满足,它应该自动启用。这不是很有效,因为它必须计算所有命令。
public RelayCommand ReadSettingsCommand
{
get
{
return _readSettingsCommand
?? (_readSettingsCommand = new RelayCommand(ExecuteReadSettings, () => IsScannedDeviceAvailable && !IsUpdateInProgress));
}
}
public class FooCommand : ICommand
{
private bool _canExecute;
private Action _delegate;
public event EventHandler CanExecuteChanged;
public new bool CanExecute
{
get
{
return _canExecute;
}
set
{
_canExecute = value;
if(CanExecuteChanged != null)
CanExecuteChanged();
}
}
public void Execute(object parameter)
{
_delegate();
}
bool ICommand.CanExecute()
{
return CanExecute;
}
public FooCommand(Action action)
{
_delegate = action;
}
}