2016-11-05 87 views
2

我不是c#的專家,但我想要做的是更新後臺工作進度條。我正在使用以下代碼:C#ProgressBar backgroundworker中的數據綁定

progressBar1.DataBindings.Add("Value", _dm, "Progress", true, 
           DataSourceUpdateMode.OnPropertyChanged); 

在GUI線程上執行時沒有後臺工作程序時可以使用。 Progress屬性是一個更新(使用INotifyPropertyChanged)來自另一個背景工作者(我無權訪問)的進度的屬性。

我該如何使它工作,以便使用backgroundworker更新而不是將它全部放在GUI線程上?

我的代碼(簡化):

class DownloadManager : INotifyPropertyChanged { 
    public event PropertyChangedEventHandler PropertyChanged; 

    private double _progressValue; 

    public double Progress 
    { 
     get { return _progressValue; } 
     private set 
     { 
      if (!value.Equals(_progressValue)) 
      { 
       _progressValue = value; 
       PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Progress")); 
      } 
     } 
    } 

    public void Download() 
    { 
     var downloader = new Downloader(); 

     downloader.DownloadProgressChanged += (sender, e) 
       => Progress = e.ProgressPercentage; 

     downloader.Execute(); 
    } 
} 

public partial class MainForm 
{ 
    private readonly DownloadManager _dm; 
    public MainForm() 
    { 
     InitializeComponent(); 
     _dm = new DownloadManager(); 
    } 

    private void btnDownload_Click(object sender, EventArgs e) 
    { 
      //TRIED HERE ... 
      progressBar1.DataBindings.Add("Value", _dm, "Progress", true, 
              DataSourceUpdateMode.OnPropertyChanged); 
      bwDownload.RunWorkerAsync(); 
     } 
    } 

    private void bwDownload_DoWork(object sender, DoWorkEventArgs e) 
    { 
     //AND TRIED HERE 
     progressBar1.DataBindings.Add("Value", _dm, "Progress", true, DataSourceUpdateMode.OnPropertyChanged); 

     //THIS AINT WORKING EITHER 
     if (progressBar1.InvokeRequired) { 
      progressBar1.Invoke(new MethodInvoker(() 
       => progressBar1.DataBindings.Add("Value", _dm, "Progress", true, 
             DataSourceUpdateMode.OnPropertyChanged))); 
    } 

     _dm.Download(); 
    } 
} 

回答

2

數據綁定應在構造函數來創建的,因爲你只需要創建每一個需要它的時候綁定一次,而不是:

public MainForm() 
{ 
    InitializeComponent(); 
    _dm = new DownloadManager(); 
    progressBar1.DataBindings.Add("Value", _dm, "Progress", true, DataSourceUpdateMode.OnPropertyChanged); 
} 

您的代碼不工作,因爲你試試從非ui線程更新UI。你需要需要使用代理屬性表上包裹的代碼Invoke()調用,例如:

public partial class MainForm 
{ 
    private double _progress; 
    public double Progress 
    { 
     get { return _progress; } 
     set 
     { 
      _progress = value; 

      // If not in the UI thread -> wrap the update in an Invoke() call: 
      if (this.InvokeRequired) 
      { 
       this.Invoke(new Action(() => progressBar1.Value = (int) _progress), new object[] { }); 
       return; 
      } 

      // Else update directly 
      progressBar1.Value = (int) value; 
     } 
    } 

    private readonly DownloadManager _dm; 
    public MainForm() 
    { 
     InitializeComponent(); 
     _dm = new DownloadManager(); 

     // Bind _db.Progress <-> this.Progress 
     DataBindings.Add("Progress", _dm, "Progress", true, DataSourceUpdateMode.OnPropertyChanged); 
    }