【问题标题】:WPF Progressbar Stops after a Few BarsWPF 进度条在几个栏后停止
【发布时间】:2013-03-15 09:55:10
【问题描述】:

在我的 WPF 应用程序中,我必须在计时器滴答事件中显示进度条进度,如下所示,

System.Windows.Forms.Timer timer;
public MainWindow()
{
    timer = new System.Windows.Forms.Timer();
    timer.Interval = 1000;
    this.timer.Tick += new System.EventHandler(this.timer_Tick);
}

如下加载事件

private void Window_Loaded(object sender, RoutedEventArgs e)
{
      progressBar1.Minimum = 0;
      progressBar1.Value = DateTime.Now.Second;
      progressBar1.Maximum = 700;
      timer.Start();         
 }

最后在tick事件中,

private void timer_Tick(object sender, EventArgs e)
{
    Duration duration = new Duration(TimeSpan.FromSeconds(20));

    //progress bar animation
    System.Windows.Media.Animation.DoubleAnimation doubleanimation = new    System.Windows.Media.Animation.DoubleAnimation(200.0, duration);
    progressBar1.BeginAnimation(ProgressBar.ValueProperty, doubleanimation);
}

当程序的进度条显示 2-3 条的进度时,它会停止递增。以后对进度完全没有影响。

为什么?

【问题讨论】:

  • 为什么要使用计时器来启动动画?而且您使用了错误的计时器。 System.Windows.Forms.Timer 用于 winforms 应用程序。请改用DispatcherTimer

标签: c# wpf timer progress-bar


【解决方案1】:

由于您的 ProgressBar 与任何特定行为无关,因此它看起来像是 indeterminate 酒吧的工作。

This other SO question 提供了一些关于它的见解。简而言之,它是 XAML 单行代码:

<!-- MinVal, MaxVal, Height needed for this to work -->
<ProgressBar x:Name="progressBar1" Margin="5" IsIndeterminate="True" 
    MinimumValue="0" MaximumValue="700" value="0" Height="20"/> 

然后在代码中,你会这样:

progressBar1.IsIndeterminate = true; // start animation
progressBar1.IsIndeterminate = false; // stop animation

【讨论】:

    【解决方案2】:

    在我的 WPF 应用程序中,我有 ... System.Windows.Forms.Timer timer;

    那是错误的计时器类型。请改用DispatcherTimer

    当我执行我的程序时,进度条显示两三个条的进度,然后停止

    这让我感到惊讶,我根本没想到它会起作用。 这意味着您可能还有其他问题,例如阻塞主(调度程序)线程。

    您只需在 Loaded 事件中设置一次值:

         progressBar1.Value = DateTime.Now.Second;
    

    Tick 事件中的progressBar1.Value 没有变化。所以它认为它停止了移动。

    【讨论】:

      【解决方案3】:

      使用 DispatcherTimer 代替 Timer(Forms 对象),并使用 ProgressBar 的 Value 属性。

      试试这个:

      MainWindows.xaml:

      <Window x:Class="WpfApplication1.MainWindow"
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              Title="MainWindow" Height="55" Width="261">
          <Grid>
              <ProgressBar Name="pb" Maximum="60" />
          </Grid>
      </Window>
      

      MainWindows.xaml.cs:

      using System.Windows;
      using System.Windows.Threading;
      
      namespace WpfApplication1
      {
          public partial class MainWindow : Window
          {
              private DispatcherTimer timer;
          
              public MainWindow()
              {
                  InitializeComponent();
      
                  this.timer = new DispatcherTimer();
                  this.timer.Tick += timer_Tick;
                  this.timer.Interval = new System.TimeSpan(0, 0, 1);
                  this.timer.Start();
              }
      
              private void timer_Tick(object sender, System.EventArgs e)
              {
                  this.pb.Value = System.DateTime.Now.Second % 100;
              }
          }
      }
      

      您可以通过更改 Value 属性来更改进度条的行为(不要忘记在 xaml 中定义 Maximum 属性)。

      【讨论】:

        【解决方案4】:

        我发现这个 (WPF Multithreading: Using the BackgroundWorker and Reporting the Progress to the UI. link) 包含一个很好的解决方案,可以满足我的需求,尽管它带有一个对话框。

        我发现非常有用的一件事是工作线程无法访问 MainWindow 的控件(以它自己的方法)。但是,当在主窗口事件处理程序中使用委托时,这是可能的。

        worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
        {
            pd.Close();
            // Get a result from the asynchronous worker
            T t = (t)args.Result
            this.ExampleControl.Text = t.BlaBla;
        };
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-03
          • 2012-12-20
          • 1970-01-01
          • 2018-01-16
          • 1970-01-01
          相关资源
          最近更新 更多