Alright, let me try to explain.
I have an application where I can trigger some sort of scan process. This scan process launches (just a number) 10 background workers which do something. After (again, just a number) 5 seconds I would like to
- Kill all the background workers (I'm using CancelAsync for that)
- Do some calculation with the data I got from all of them
- Update the UI so the data is displayed AND enable some buttons (these buttons are bound through a
ViewModel
Command called PerformUpdateCommand
and they have a CanExecute
property of IsPerformUpdateAllowed
. The IsPerformUpdateAllowed
dependency property is set when my tasks finish.
What I thought I would do:
- After triggering the Background Workers, start a dispatcher timer with a 5 second interval.
- When the
DispatcherTimer
"ticks" I calculate the data and set the property IsPerformUpdateAllowed
to either true or false.
This basically works as expected (the UI stays responsive, ...) with just a minor hickup: The UI is not being updated (the button is not enabled). As soon as I put the window into the background and back into the foreground, the command is enabled, also the IsPerformUpdateAllowed
property is set to true. Also, when I press the button (in disabled state) after pressing it, it will be enabled.
So, although I set the dependency property correctly, the UI does not react to this change.
Anybody knows why? Interestingly, I also set some text in the UI into a label - this text is updated correctly. It's just that the property which tells the command CanExecute
does not trigger a UI update.
Code for the initialization of the timer.
_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();
Code how the Command is bound to the WPF element (the button is actually a Hyperlink):
<Label Grid.Row="1" Grid.Column="1">
<Hyperlink Command="{Binding ReadSettingsCommand}">
<TextBlock Text="{Binding Source={StaticResource Loc}, Path=Labels.ReadSettings}"></TextBlock>
</Hyperlink>
</Label>
Here is the code for the Command
public RelayCommand ReadSettingsCommand
{
get
{
return _readSettingsCommand
?? (_readSettingsCommand = new RelayCommand(ExecuteReadSettings, () => IsScannedDeviceAvailable && !IsUpdateInProgress));
}
}
The code is actually dependent on two dependency properties IsScannedDeviceAvailable AND NOT IsUpdateInProgress. Both are dependency properties.
UPDATE: I just read that the binding to the CanExecute property is just one time. If you want it to revalidate you need to call RaiseCanExecuteChanged on the command. This works, but it is somewhat cumbersome, since now I need to call it manually every time one of the two properties change. Actually I wanted that to be handled automatically. Any ideas on how this can be done more easily? Isn't there some method to have kind of a one-way binding between CanExecute and the property?