好吧,让我试着解释一下。
我有一个可以触发某种扫描过程的应用程序。这个扫描过程会启动(只是一个数字)10 个后台工作人员来做一些事情。(再次,只是一个数字)5秒后,我想
- 杀死所有后台工作人员(我为此使用 CancelAsync)
- 用我从他们那里得到的数据做一些计算
- 更新 UI 以便显示数据并启用一些按钮(这些按钮通过
ViewModel
调用的命令绑定,PerformUpdateCommand
并且它们具有.CanExecute
属性IsPerformUpdateAllowed
。IsPerformUpdateAllowed
当我的任务完成时设置依赖属性。
我想我会做什么:
- 触发后台工作人员后,以 5 秒的间隔启动调度程序计时器。
- 当
DispatcherTimer
“滴答声”时,我计算数据并将属性设置IsPerformUpdateAllowed
为真或假。
这基本上可以按预期工作(UI 保持响应,...),只是一个小问题:UI 没有被更新(按钮未启用)。一旦我将窗口置于后台并回到前台,该命令就会启用,该IsPerformUpdateAllowed
属性也设置为 true。此外,当我按下按钮(处于禁用状态)后,它将被启用。
因此,尽管我正确设置了依赖属性,但 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 元素的代码(按钮实际上是一个超链接):
<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 而不是 IsUpdateInProgress。两者都是依赖属性。
更新:我刚刚读到与 CanExecute 属性的绑定只是一次。如果您希望它重新验证,您需要在命令上调用 RaiseCanExecuteChanged。这可行,但有点麻烦,因为现在我需要在每次两个属性之一更改时手动调用它。实际上我希望自动处理它。关于如何更轻松地完成此操作的任何想法?难道没有某种方法可以在 CanExecute 和属性之间建立一种单向绑定吗?