WPF的进度条不会在最后的ProgressChanged更新 [英] wpf progressbar doesn't update on last ProgressChanged

查看:287
本文介绍了WPF的进度条不会在最后的ProgressChanged更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我制作了一些UI,并且其中有ProgressBar.使用MVVM模式.

I making some UI and I have ProgressBar in it. Using MVVM pattern.

XAML:

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

ViewModel(简体):

ViewModel (simplified):

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

是问题所在.如您所见,该行关闭了窗口.如果我对该行发表评论,progressbar效果很好. 10、20、30,... 100%我明白了.但是其他情况下,进度条看起来像是10%,20%,30%... 90%,有些等待并且窗口关闭!我尝试使用Thread.Sleep(5000),给进度条一些绘图时间.但是,即使那样也无济于事.那么,如果在此之后立即关闭窗口,我怎么能看到最后的状态变化?

is the problem. That line close window as u see. If I comment that line, progressbar works good. 10, 20, 30, ... 100% I see. But else, progressbar looks like 10, 20, 30, ... 90%, some waiting and window closing! I try to use Thread.Sleep(5000), to give the progressbar some time to drawing. But even that doesn't help. So, how can I see last persentage change if window closing immediately after that?

推荐答案

对于以后的读者:

BackgroundWorker的 DoWork在新线程,从而可以在不锁定UI的情况下进行工作. RunWorkerCompleted功能将为您在调用线程上运行,这意味着它又回到了UI线程上,在此完成的任何工作都可以锁定UI.

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正在通过其他线程进行更新,从而可以对其进行更新.但是,一旦值从90变为100,UI就会执行此Close.当OP添加了Sleep(5000)时;它位于UI线程的Completed中,因此阻止了ProgressBar完整显示100%.

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%.

解决方案是在发送关闭消息之前将睡眠从Completed移入DoWork循环,或者至少在循环之后,以查看ProgressBar达到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.

这篇关于WPF的进度条不会在最后的ProgressChanged更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆