[英]implementing progress bar in wpf window with viewmodel
我有WPF窗口( MainWindow
.cs),它具有按钮和进度条。
按钮绑定到我的视图模型中的命令
<Button Command="{Binding StartMyWork}" Content="Run" Width="200" Height="50"/>
进度条也绑定到ViewModel中的CurrentProgress属性
<ProgressBar Value="{Binding CurrentProgress, Mode=OneWay}" Width="400"/>
MainWindowViewModel.cs
private ICommand _StartMyWork;
public ICommand StartMyWork;
{
get {
if (_StartMyWork == null) {
_StartMyWork = new RelayCommand(
x => this.DoSomeDummyWork(this.MySelectedComboValue)
);
}
return _StartMyWork;
}
}
private void DoSomeDummyWork(string mySelectedComboProp)
{
// here I want to simulate some work
// and make ui responsive and introduce progressbar
}
我在想用这个答案
所以我添加了相同的视图模型
private ICommand _InstigateWorkCommand;
private double _CurrentProgress;
private BackgroundWorker _Worker;
private void DoSomeDummyWork(string mySelectedComboProp)
{
// here I want to simulate some work
// and make ui responsive and introduce progressbar
_InstigateWorkCommand = new RelayCommand(x => _Worker.RunWorkerAsync(), x => !_Worker.IsBusy);
_Worker = new BackgroundWorker();
_Worker.DoWork += DoWork;
_Worker.ProgressChanged += this.ProgressChanged;
}
private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
_CurrentProgress = e.ProgressPercentage;
}
public double CurrentProgress
{
get { return _CurrentProgress; }
private set {
if (_CurrentProgress != value){
_CurrentProgress = value;
OnPropertyChanged("CurrentProgress");
}
}
}
private void DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 10; i++) {
Thread.Sleep(1000);
_CurrentProgress = i;
}
}
private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
_CurrentProgress = e.ProgressPercentage;
}
在实现进度条时我错了的地方,我在DoWork方法中设置了断点,尽管第一个命令StartMyWork可以按预期工作,但它从未被击中。
首先,删除第二个命令ICommand _InstigateWorkCommand; 您不需要它,至少到目前为止,它只会使您感到困惑。
在执行第一个命令的方法(DoSomeDummyWork)中 ,删除这些lambda表达式行_InstigateWorkCommand = new RelayCommand(x => _Worker.RunWorkerAsync(),x =>!_Worker.IsBusy);
并把这个
_Worker = new BackgroundWorker();
_Worker.WorkerReportsProgress = true;
_Worker.DoWork += DoWork;
_Worker.ProgressChanged += new ProgressChangedEventHandler(ProgressChanged);
_Worker.RunWorkerAsync();
DoWork方法也应该像这样
private void DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 10; i++)
{
Thread.Sleep(1000);
_Worker.ReportProgress(i*(100/10));
}
}
private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
_CurrentProgress = e.ProgressPercentage;
OnPropertyChanged("CurrentProgress");
}
您现在还应该添加方法,一旦迭代完成,该方法将被调用
void workerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Complete!");
}
并连线此方法
_Worker.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(workerCompleted);
*仅提及RunWorkerCompleted
事件将触发,无论bg如何。 线程已完成-正常完成还是抛出异常(取消操作)。 虽然如果您关闭应用程序的同时bg。 运行该应用程序的工作人员将立即退出,而无需等待bg。 线程完成。*
您需要通过某种交互来激活_InstigateWorkCommand,否则您将永远不会开始实际的更新。 如果您想停止使用_InstigateWorkCommand并在单击绑定到StartMyWork的按钮时将其启动,则需要将RunWorkerAsync代码从RelayCommand绑定上移一个级别。
例如:
private void DoSomeDummyWork(string mySelectedComboProp)
{
// here I want to simulate some work
// and make ui responsive and introduce progressbar
_Worker = new BackgroundWorker();
_Worker.DoWork += DoWork;
_Worker.ProgressChanged += this.ProgressChanged;
_Worker.RunWorkerAsync();
}
哦,还不完整。 如Maximus所说,在您的DoSomeDummyWork
方法的末尾添加_Worker.RunWorkerAsync()
。 然后:
private void DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 10; i++) {
Thread.Sleep(1000);
_CurrentProgress = i;
}
}
不是_CurrentProgress
,而是CurrentProgress
。 它将通知您的ProgressBar有关更改。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.