使用WPF和MVVM模式实现进度条(使用BackgroundWorker)
注意:此代码现在可以运行。我已经修复了一些愚蠢的错误,并且正如 Steve Greatrex 指出的那样,我还修改了代码。
原始发布链接 如何实现进度使用 MVVM 模式的栏
ProgressbarSampleView.xaml
<UserControl x:Class="MyProject.ProgressbarSampleView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="718" Width="1024">
<ProgressBar Grid.Row="1"
Value="{Binding CurrentProgress, Mode=OneWay}"
Visibility="{Binding ProgressVisibility}"
Margin="22,0,25,0" />
<Button Grid.Row="2"
Content="Start Now"
Height="30"
Width="80"
HorizontalAlignment="Left"
Margin="22,4,0,0"
Name="btnStartNow"
VerticalAlignment="Top"
Command="{Binding Path=InstigateWorkCommand}"
/>
</UserControl>
ProggressbarSampleViewModel.cs
namespace MyProject
{
public class ProggressbarSampleViewModel: ViewModelBase
{
private readonly BackgroundWorker worker;
private readonly ICommand instigateWorkCommand;
public ProggressbarSampleViewModel()
{
this.instigateWorkCommand = new
RelayCommand(o => this.worker.RunWorkerAsync(), o => !this.worker.IsBusy);
this.worker = new BackgroundWorker();
this.worker.DoWork += this.DoWork;
this.worker.ProgressChanged += this.ProgressChanged;
}
public ICommand InstigateWorkCommand
{
get { return this.instigateWorkCommand; }
}
private int _currentProgress;
public int CurrentProgress
{
get { return this._currentProgress; }
private set
{
if (this._currentProgress != value)
{
this._currentProgress = value;
OnPropertyChanged("CurrentProgress");
}
}
}
private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.CurrentProgress = e.ProgressPercentage;
}
private void DoWork(object sender, DoWorkEventArgs e)
{
// do time-consuming work here, calling ReportProgress as and when you can
for (int i = 0; i < 100; i++)
{
Thread.Sleep(1000);
_currentProgress = i;
OnPropertyChanged("CurrentProgress");
}
}
}
Note: This code works now. I have fixed some stupid mistake and I have also revised code as Steve Greatrex pointed out.
Original Posting LINK How to implement a progress bar using the MVVM pattern
ProgressbarSampleView.xaml
<UserControl x:Class="MyProject.ProgressbarSampleView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="718" Width="1024">
<ProgressBar Grid.Row="1"
Value="{Binding CurrentProgress, Mode=OneWay}"
Visibility="{Binding ProgressVisibility}"
Margin="22,0,25,0" />
<Button Grid.Row="2"
Content="Start Now"
Height="30"
Width="80"
HorizontalAlignment="Left"
Margin="22,4,0,0"
Name="btnStartNow"
VerticalAlignment="Top"
Command="{Binding Path=InstigateWorkCommand}"
/>
</UserControl>
ProggressbarSampleViewModel.cs
namespace MyProject
{
public class ProggressbarSampleViewModel: ViewModelBase
{
private readonly BackgroundWorker worker;
private readonly ICommand instigateWorkCommand;
public ProggressbarSampleViewModel()
{
this.instigateWorkCommand = new
RelayCommand(o => this.worker.RunWorkerAsync(), o => !this.worker.IsBusy);
this.worker = new BackgroundWorker();
this.worker.DoWork += this.DoWork;
this.worker.ProgressChanged += this.ProgressChanged;
}
public ICommand InstigateWorkCommand
{
get { return this.instigateWorkCommand; }
}
private int _currentProgress;
public int CurrentProgress
{
get { return this._currentProgress; }
private set
{
if (this._currentProgress != value)
{
this._currentProgress = value;
OnPropertyChanged("CurrentProgress");
}
}
}
private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.CurrentProgress = e.ProgressPercentage;
}
private void DoWork(object sender, DoWorkEventArgs e)
{
// do time-consuming work here, calling ReportProgress as and when you can
for (int i = 0; i < 100; i++)
{
Thread.Sleep(1000);
_currentProgress = i;
OnPropertyChanged("CurrentProgress");
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
StartNowCommand
从不调用BackgroundWorker
- 它只是在 UI 线程上同步执行DoStartNow
方法。基于此,我猜测当您单击链接到 StartNow 命令的按钮时,您会看到 UI 冻结了..?您应该将按钮绑定到实际上异步运行
BackgroundWorker
代码的InstigateWorkCommand
。在此实现中,我认为您根本不需要
StartNowCommand
。我也没有在视图模型中的任何位置看到DoWork
事件处理程序,因此我假设它只是调用DoStartNow
The
StartNowCommand
never invokes theBackgroundWorker
- it just synchronously executes theDoStartNow
method on the UI thread. Based on this, I'd guess that when you click on the button linked to theStartNow
command you see your UI freeze up..?You should be binding your button to the
InstigateWorkCommand
which actually runsBackgroundWorker
code asynchronously.In this implementation I don't think you would need the
StartNowCommand
at all. I also don't see theDoWork
event handler anywhere in your view model, so I'm assuming that it just callsDoStartNow