2013-09-26 87 views
1

我製作了一些用戶界面,並在其中有ProgressBar。使用MVVM模式。wpf progressbar不會在上一次更新ProgressChanged

XAML:

<ProgressBar Grid.Row="2" Minimum="0" Maximum="100" Value="{Binding CurrentProgress, Mode=OneWay}"/> 

視圖模型(簡化):

class MyClass : ViewModelBase 
{ 
    /// <summary> 
    /// Fields 
    /// </summary> 
    private int _currentProgress; 
    private readonly BackgroundWorker _worker; 
    private int _step; 

    /// <summary> 
    /// Properties 
    /// </summary> 
    public int CurrentProgress 
    { 
     get 
     { 
      return _currentProgress; 
     } 
     set 
     { 
      if (_currentProgress != value) 
      { 
       _currentProgress = value; 
       RaisePropertyChanged("CurrentProgress"); 
      } 
     } 
    } 

    /// <summary> 
    /// Constructor 
    /// </summary> 
    public MyClass() 
    { 
     _step = 10; 
     _currentProgress = 0; 
     _worker = new BackgroundWorker(); 
     _worker.DoWork += DoWork; 
     _worker.WorkerReportsProgress = true; 
     _worker.ProgressChanged += ProgressChanged; 
     _worker.RunWorkerCompleted += RunWorkerCompleted; 
    } 

    /// <summary> 
    /// Command 
    /// </summary> 
    private RelayCommand _myCommand; 
    public RelayCommand MyCommand 
    { 
     get 
     { 
      return _myCommand ?? (_myCommand = 
       new RelayCommand(_worker.RunWorkerAsync, CanMyCommand)); 
     } 
    } 

    private bool CanMyCommand() 
    { 
     return true; 
    } 

    /// <summary> 
    /// Handlers 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    private void DoWork(object sender, DoWorkEventArgs e) 
    { 
     for (int i = 0; i < 10; i++) 
      ConsumingMethod(); 
    } 

    private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     Thread.Sleep(5000); 
     Messenger.Default.Send(new CloseAddDocumentWindow(String.Empty)); 
    } 

    private void ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     CurrentProgress = e.ProgressPercentage; 
    } 

    /// <summary> 
    /// Method 
    /// </summary> 
    private void ConsumingMethod() 
    { 
     CurrentProgress += _step; 
    } 
} 

代碼隱藏:

Messenger.Default.Register<CloseAddDocumentWindow>(this, nm => 
{ 
     if (nm.Sender == DataContext) 
      Close(); 
}); 

所以,這

Messenger.Default.Send(new CloseAddDocumentWindow(String.Empty)); 

是問題所在。你看到的那一行關閉窗口。如果我評論該行,進度欄的效果很好。 10,20,30,... 100%我明白了。但是,其他進度條看起來像10,20,30 ... 90%,有些正在等待,窗戶關閉!我嘗試使用Thread.Sleep(5000),爲進度條提供一些繪製時間。但即使這樣也無濟於事。那麼,如果在此之後立即關閉窗口,我怎麼才能看到最後的更改?

+0

將睡眠放在Completed中將無濟於事,您正在睡覺調用線程,這是UI。在更改爲「CurrentProgress」之後,將你的睡眠轉移到'ConsumingMethod()'中,看看是否這樣做。 – bland

+0

真的有用。謝謝 – monstr

回答

0

對於任何未來的讀者:

BackgroundWorker'sDoWork是在一個新的線程執行,允許在不鎖定,例如用戶界面發生的工作。 RunWorkerCompleted功能將在您的調用線程上運行,這意味着它將返回到UI線程,並且此處完成的任何工作都可以鎖定UI。

ProgressBar正在通過不同的線程進行更新,允許更新。但只要數值從90到100,UI就會執行此關閉。當OP添加了Sleep(5000)時;它在Completed中是UI線程,從而阻止ProgressBar完整顯示100%。

解決方法是在發送關閉之前將睡眠狀態從「完成」移動到DoWork循環中,或者至少在循環之後,將ProgressBar命中100%。

相關問題