1

我制作了一些 UI,里面有 ProgressBar。使用 MVVM 模式。

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),给进度条一些时间来绘制。但即使这样也无济于事。那么,如果在此之后立即关闭窗口,我怎么能看到最后的变化?

4

1 回答 1

0

对于任何未来的读者:

BackgroundWorker's DoWork is performed on a new thread, allowing work to occur without locking the UI for instance. The RunWorkerCompleted functionality will be ran on the calling thread for you, this means it is back on the UI thread and any work done here can lock the UI.

ProgressBar is being updated via different thread, allowing it to update. But as soon as the value goes from 90 to 100, the UI is performing this Close. When OP added the Sleep(5000); it was in the Completed which is the UI thread thus preventing the ProgressBar from showing a full 100%.

Resolution is to move the sleep from Completed into the DoWork loop, or at least after the loop, to see the ProgressBar hit 100%, before sending the close.

于 2013-09-26T12:41:20.110 回答