0
votes

On button click in Word VSTO addin, I want to show the form with progress bar and update its value.

Even though I used BackgroundWorker and its events (DoWork, ProgressChanged), progress of the progress bar does not update accordingly

private void extractDataButton_Click(object sender, RibbonControlEventArgs e)
{
    //On button click of addin
    ProgressNotifier progressNotifier = new ProgressNotifier();
    progressNotifier.Show();
    progressNotifier.UpdateProgressBar(10);  

    // Does the work which lasts few seconds
    HandleRetrievedData(data);
    progressNotifier.UpdateProgressBar(100);
    progressNotifier.Close();
}



// Progress bar form
public partial class ProgressNotifier : Form
{
    public ProgressNotifier()
    {
        InitializeComponent();
    }

    public void UpdateProgressBar(int progress)
    {   
        backgroundWorker1.ReportProgress(progress);
        progressBar_extractionProgress.Update();
    }

    private void backgroundWorker1_ProgressChanged(object sender, 
      ProgressChangedEventArgs e)
    {
        this.progressBar_extractionProgress.Value = e.ProgressPercentage;
    }
} 
1
I believe it's due to the fact, that the BackgroundWorker runs on a sperate Thread from your Main-/UI-Thread, so you'll have to invoke the changes on the UI-Thread: Application.Current.Dispatcher.Invoke(() => this.progressBar_extractionProgress.Value = e.ProgressPercentage);Tobias Tengler
It's a WinForms application hence Application.Current returns null. Is there any other way to invoke Dispatcher?Kokos34
I think you could just invoke the Control itself, been a while since I worked with WinForms, but give this a try: this.progressBar_extractionProgress.Invoke(() => this.progressBar_extractionProgress.Value = e.ProgressPercentage);Tobias Tengler

1 Answers

0
votes

Although this is an older style using delegates, you might need a check that the form is available for updating. Below is older code - there are examples using newer syntax not requiring delegates - but generally illustrates a resolve.

    private delegate void StatusMessage();

    /// <summary>
    ///     Simple methods for setting active cube list before connecting
    /// </summary>
    private void SetDefaultNode()
    {
        if (this.ActiveCubeStatus.InvokeRequired)
        {
            StatusMessage d = new StatusMessage(SetDefaultNodeDirect);
            this.Invoke(d);
        }
        else
        {
            SetDefaultNodeDirect();
        }
    }

    /// <summary>
    ///     Simple methods for setting active cube list before connecting
    /// </summary>
    private void SetDefaultNodeDirect()
    {
        //clears treeveiw
        ClearActiveCubes();

        //create default inactive node
        TreeNode nodeDefault = new TreeNode();
        nodeDefault.Name = "Waiting";
        nodeDefault.Text = "Waiting on connection...";
        this.ActiveCubeStatus.Nodes.Add(nodeDefault);
        nodeDefault = null;
    }