使用WPF和MVVM模式实现进度条(使用BackgroundWorker)

发布于 2024-12-08 11:03:20 字数 2683 浏览 0 评论 0原文

注意:此代码现在可以运行。我已经修复了一些愚蠢的错误,并且正如 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

墟烟 2024-12-15 11:03:20

StartNowCommand 从不调用 BackgroundWorker - 它只是在 UI 线程上同步执行 DoStartNow 方法。基于此,我猜测当您单击链接到 StartNow 命令的按钮时,您会看到 UI 冻结了..?

您应该将按钮绑定到实际上异步运行 BackgroundWorker 代码的 InstigateWorkCommand

在此实现中,我认为您根本不需要 StartNowCommand。我也没有在视图模型中的任何位置看到 DoWork 事件处理程序,因此我假设它只是调用 DoStartNow

The StartNowCommand never invokes the BackgroundWorker - it just synchronously executes the DoStartNow method on the UI thread. Based on this, I'd guess that when you click on the button linked to the StartNow command you see your UI freeze up..?

You should be binding your button to the InstigateWorkCommand which actually runs BackgroundWorker code asynchronously.

In this implementation I don't think you would need the StartNowCommand at all. I also don't see the DoWork event handler anywhere in your view model, so I'm assuming that it just calls DoStartNow

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文