0

I have wpf window (MainWindow.cs) which has button and progress bar.

Button is bound to command inside my viewmodel

<Button Command="{Binding StartMyWork}" Content="Run" Width="200" Height="50"/>

progress bar is bound to CurrentProgress property also in viewmodel

<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    
}

I was thinking using this answer

So I added in the same viewmodel

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;
}

Where I'm wrong in implementing progress bar, I set breakpoint in DoWork method which is never hitted, although first command StartMyWork works as expected.

5
  • 1
    Add _Worker.RunWorkerAsync(), you never call _Worker.ReportProgress(value) so ProgressChanged will never be invoked. Commented Aug 29, 2014 at 19:51
  • please can you be specific, I already have _Worker.RunWorkerAsync(), .. inside DoSomeDummyWork method. Commented Aug 29, 2014 at 19:53
  • I dont know why you're being so rude, he's right, it's getting called in his lamba right at the top of DoSomeDummywork in the view model, and he's got no edits on the question. Commented Aug 29, 2014 at 20:16
  • I think he just kept it in the InstigateWork relaycommand by mistake. Commented Aug 29, 2014 at 20:27
  • if _StartMyWork;== null) isn't going to compile. Please post correct code to avoid all sorts of confusion. Commented Aug 29, 2014 at 21:05

3 Answers 3

4

First of all, remove your second command ICommand _InstigateWorkCommand; you dont need it, at least for now, it just makes you confuse.

Inside your method (DoSomeDummyWork) which first command executes remove those lambda expression line _InstigateWorkCommand = new RelayCommand(x => _Worker.RunWorkerAsync(), x => !_Worker.IsBusy);
and put this

 _Worker = new BackgroundWorker();
 _Worker.WorkerReportsProgress = true;
 _Worker.DoWork += DoWork;                        
 _Worker.ProgressChanged += new ProgressChangedEventHandler(ProgressChanged);
_Worker.RunWorkerAsync();

also DoWork method should look like this

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");
}

Also you should now add method which will be called once iteration is completed

void workerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    MessageBox.Show("Complete!");
}

and wire this method

_Worker.RunWorkerCompleted += 
      new RunWorkerCompletedEventHandler(workerCompleted);

*Just to mention that RunWorkerCompleted event fires, no matter how the bg. thread completed - wheter it completed normally or an exception is thrown (cancel action). Although if you shut down application while the bg. worker running the application will immediatly exit without waiting bg. thread to complete.*

Sign up to request clarification or add additional context in comments.

1 Comment

key line is OnPropertyChanged("CurrentProgress") i believe, what is the difference between having in the progresschanged function vs having like original questions in the property constructor. obviously your one works and other one doesnt work but why? does it not trigger when property changes?
1

You'll need to activate your _InstigateWorkCommand with some kind of interaction or you'll never kick off the actual update. If you want to instead stop using _InstigateWorkCommand and just kick it off when you click the button bound to StartMyWork, than you'll need to move the RunWorkerAsync code up a level out of the RelayCommand binding.

Ex:

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();
}

Comments

0

Oh, not full answer. As Maximus said, add _Worker.RunWorkerAsync() to the end of your DoSomeDummyWork method. Then:

private void DoWork(object sender, DoWorkEventArgs e)
{
   for (int i = 0; i < 10; i++) {
       Thread.Sleep(1000);
       _CurrentProgress = i;
   }
}

Not _CurrentProgress, but CurrentProgress. It will notify your ProgressBar about changes.

2 Comments

He already set up the runworkerasync in a relay command at the top of his viewmodel.
As I understand, if he retained old command, new would not be called. If he changed main command to this, whole DoSomeDummyWork would not be executed

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.