Reputation: 977
I'm binding the visibility of a ProgressBar to a property that returns true if a specific task is running:
View:
<ProgressBar IsIndeterminate="True"
Visibility="{Binding TaskRunning, Converter={StaticResource boolToVisibilityConverter}}"/>
ViewModel:
private Task someTask;
private CancellationTokenSource cancellationTokenSource;
public bool TaskRunning
{
get
{
return someTask!= null && someTask.Status == TaskStatus.Running;
}
}
private void StartTaskHandler()
{
someTask = Task.Run(new Action(() =>
{
// Simulate some work
cancellationTokenSource.Token.WaitHandle.WaitOne(10000);
}), cancellationTokenSource.Token);
someTask.ContinueWith((task) => RaisePropertyChanged("TaskRunning"));
RaisePropertyChanged("TaskRunning");
}
When executing StartTaskHandler
the ProgressBar will only sometimes turn visible. Why is that? How can I make sure the ProgressBar is visible when the task is running?
Upvotes: 1
Views: 712
Reputation: 38189
I highly recommend to you to rename your property TaskRunning
to IsBusy
as it is good practice to name bool
variables with prefix is
.
You should have setter in your property TaskRunning to set true
value:
private bool _isBusy;
public bool IsBusy
{
get { return _isBusy; }
set
{
_isBusy = value;
RaisePropertyChanged("IsBusy");
}
}
and at your code:
private void StartTaskHandler()
{
IsBusy=true;
someTask = Task.Run(new Action(() =>
{
// Simulate some work
cancellationTokenSource.Token.WaitHandle.WaitOne(10000);
}), cancellationTokenSource.Token);
someTask.ContinueWith((task) => IsBusy=false;);
}
You can raise PropertyChanged event
from any threads cause WPF automatically dispatches arguments of PropertyChanged event
to the UI thread.
Update:
Your code does not work as your property TaskRunning
is just readable, and you cannot set true
or false
values. To set values to your property you should add setter and fire an event PropertyChanged when you set new value to the property TaskRunning
:
private bool _taskRunning;
public bool TaskRunning
{
get
{
if(someTask!= null && someTask.Status == TaskStatus.Running)
_taskRunning=true;
return _taskRunning;
}
set
{
_taskRunning=value;
RaisePropertyChanged("TaskRunning");
}
}
This row of code just fires the event with the current value(not new value):
someTask.ContinueWith((task) => RaisePropertyChanged("TaskRunning"));
but this row of code will set new value of property TaskRunning
and fires event PropertyChanged
to update your UI:
someTask.ContinueWith((task) => TaskRunning=true;);
Upvotes: 1
Reputation: 977
someTask.Status
may sometimes be still TaskStatus.WaitingToRun
. Adding this will solve the issue. But it's better to use async/await:
private bool isBusy = false;
public bool IsBusy
{
get
{
return isBusy;
}
set
{
isBusy = value;
RaisePropertyChanged("IsBusy");
}
}
private async void StartTaskHandler()
{
cancellationTokenSource = new CancellationTokenSource();
IsBusy = true;
someTask = Task.Run(new Action(() =>
{
// Simulate some work
cancellationTokenSource.Token.WaitHandle.WaitOne(10000);
}), cancellationTokenSource.Token);
await someTask;
IsBusy = false;
}
Upvotes: 0