好吧,让我试着解释一下。如何强制更新MVVM中的UI?
我有一个应用程序,我可以触发某种扫描过程。这个扫描过程启动(只是一个数字)10个背景的工作人员做些事情。后(再次,只是一个数字)5秒我想
- 杀死所有的后台工作人员(我使用CancelAsync为)
- 做一些计算与我从所有这些 的获得了数据
- 更新UI,使得显示的数据,并实现一些按钮(这些按钮通过
ViewModel
命令约束称为PerformUpdateCommand
和他们的IsPerformUpdateAllowed
一个CanExecute
属性。当我的任务完成IsPerformUpdateAllowed
依赖属性设置。
我想我会做:
- 触发背景工人后,使用5秒的间隔定时器调度。
- 当
DispatcherTimer
“ticks”我计算数据并将属性IsPerformUpdateAllowed
设置为true或false。
这只是基本上按预期工作(用户界面保持响应,...)只是一个小问题:用户界面没有被更新(按钮未启用)。只要我将窗口放入背景并返回到前景中,该命令即会启用,并且IsPerformUpdateAllowed
属性也将设置为true。另外,按下按钮后(禁用状态),它将被启用。
所以,虽然我正确设置了依赖项属性,但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元件(按钮实际上是一个超链接):
<Label Grid.Row="1" Grid.Column="1">
<Hyperlink Command="{Binding ReadSettingsCommand}">
<TextBlock Text="{Binding Source={StaticResource Loc}, Path=Labels.ReadSettings}"></TextBlock>
</Hyperlink>
</Label>
下面是命令
public RelayCommand ReadSettingsCommand
{
get
{
return _readSettingsCommand
?? (_readSettingsCommand = new RelayCommand(ExecuteReadSettings,() => IsScannedDeviceAvailable && !IsUpdateInProgress));
}
}
的代码是代码实际上依赖于两个依赖项属性IsScannedDeviceAvailable AND NOT IsUpdateInProgress。两者都是依赖属性。
更新:我刚刚读到绑定到CanExecute属性只是一次。如果你想让它重新生效,你需要在命令上调用RaiseCanExecuteChanged。这可以起作用,但它有点麻烦,因为现在我需要在两个属性中的一个发生更改时手动调用它。其实我想让它自动处理。关于如何更轻松地完成这些任何想法? CanExecute和属性之间是否存在某种单向绑定的方法?
什么是您的IsPerformUpdateAllowed DependencyProperty? – markmnl
您的ICommands不会引发CanExercuteChanged事件。 – Aron
@Aron:有没有比手动调用RaiseCanExecuteChanged更好的方法? –