将可见性绑定到任务状态
本文关键字:任务 状态 绑定 可见性 | 更新日期: 2023-09-27 18:24:41
我将ProgressBar的可见性绑定到一个属性,该属性在运行特定任务时返回true:
视图:
<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");
}
执行StartTaskHandler
时,ProgressBar有时只会变为可见。为什么?如何确保ProgressBar在任务运行时可见?
我强烈建议您将属性TaskRunning
重命名为IsBusy
,因为最好使用前缀is
命名bool
变量。
您应该在属性TaskRunning中设置setter来设置true
值:
private bool _isBusy;
public bool IsBusy
{
get { return _isBusy; }
set
{
_isBusy = value;
RaisePropertyChanged("IsBusy");
}
}
和你的代码:
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;);
}
您可以从任何线程引发PropertyChanged event
,因为WPF会自动将PropertyChanged event
的参数分派到UI线程。
更新:
您的代码不起作用,因为属性TaskRunning
只是可读的,并且不能设置true
或false
值。要为属性设置值,您应该添加setter,并在为属性TaskRunning
:设置新值时激发事件PropertyChanged
private bool _taskRunning;
public bool TaskRunning
{
get
{
if(someTask!= null && someTask.Status == TaskStatus.Running)
_taskRunning=true;
return _taskRunning;
}
set
{
_taskRunning=value;
RaisePropertyChanged("TaskRunning");
}
}
这行代码只是用当前值(而不是新值)触发事件:
someTask.ContinueWith((task) => RaisePropertyChanged("TaskRunning"));
但是这一行代码将设置属性TaskRunning
的新值,并触发事件PropertyChanged
来更新您的UI:
someTask.ContinueWith((task) => TaskRunning=true;);
someTask.Status
有时可能仍然是TaskStatus.WaitingToRun
。添加此项将解决问题。但最好使用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;
}